aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authorLiGuilin <liguilin0522@qq.com>2016-10-08 08:34:12 +0800
committerLiGuilin <liguilin0522@qq.com>2016-10-08 08:34:12 +0800
commitc91da2b0c4c3d9218c0b4d1712d744bb35245a61 (patch)
treee1ae0664a4f21f3948bde8c8f9f9e55dea0cb11f /toolsrc/src
parent280d88b34033ab728e02f725d8d8ff5f9250c6de (diff)
parenta0f621c0fca2c3de8bd5249f023979b800c543cf (diff)
downloadvcpkg-c91da2b0c4c3d9218c0b4d1712d744bb35245a61.tar.gz
vcpkg-c91da2b0c4c3d9218c0b4d1712d744bb35245a61.zip
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'toolsrc/src')
-rw-r--r--toolsrc/src/BinaryParagraph.cpp38
-rw-r--r--toolsrc/src/SourceParagraph.cpp19
-rw-r--r--toolsrc/src/StatusParagraph.cpp3
-rw-r--r--toolsrc/src/StatusParagraphs.cpp23
-rw-r--r--toolsrc/src/commands_cache.cpp39
-rw-r--r--toolsrc/src/commands_create.cpp37
-rw-r--r--toolsrc/src/commands_edit.cpp33
-rw-r--r--toolsrc/src/commands_help.cpp10
-rw-r--r--toolsrc/src/commands_import.cpp25
-rw-r--r--toolsrc/src/commands_installation.cpp148
-rw-r--r--toolsrc/src/commands_integration.cpp16
-rw-r--r--toolsrc/src/commands_list.cpp32
-rw-r--r--toolsrc/src/commands_other.cpp225
-rw-r--r--toolsrc/src/commands_owns.cpp16
-rw-r--r--toolsrc/src/commands_remove.cpp7
-rw-r--r--toolsrc/src/commands_search.cpp64
-rw-r--r--toolsrc/src/commands_update.cpp94
-rw-r--r--toolsrc/src/lib.cpp103
-rw-r--r--toolsrc/src/main.cpp48
-rw-r--r--toolsrc/src/metrics.cpp2
-rw-r--r--toolsrc/src/package_spec.cpp49
-rw-r--r--toolsrc/src/package_spec_parse_result.cpp6
-rw-r--r--toolsrc/src/post_build_lint.cpp82
-rw-r--r--toolsrc/src/test.cpp26
-rw-r--r--toolsrc/src/triplet.cpp60
-rw-r--r--toolsrc/src/vcpkg_Checks.cpp3
-rw-r--r--toolsrc/src/vcpkg_Dependencies.cpp67
-rw-r--r--toolsrc/src/vcpkg_Environment.cpp22
-rw-r--r--toolsrc/src/vcpkg_Files.cpp23
-rw-r--r--toolsrc/src/vcpkg_Input.cpp52
-rw-r--r--toolsrc/src/vcpkg_Strings.cpp19
-rw-r--r--toolsrc/src/vcpkg_System.cpp4
-rw-r--r--toolsrc/src/vcpkg_cmd_arguments.cpp99
-rw-r--r--toolsrc/src/vcpkg_paths.cpp28
-rw-r--r--toolsrc/src/vcpkglib_helpers.cpp23
35 files changed, 917 insertions, 628 deletions
diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp
index 274bd879e..48d04f686 100644
--- a/toolsrc/src/BinaryParagraph.cpp
+++ b/toolsrc/src/BinaryParagraph.cpp
@@ -8,55 +8,55 @@ namespace vcpkg
{
BinaryParagraph::BinaryParagraph() = default;
- BinaryParagraph::BinaryParagraph(const std::unordered_map<std::string, std::string>& fields)
+ BinaryParagraph::BinaryParagraph(const std::unordered_map<std::string, std::string>& fields) :
+ version(required_field(fields, "Version")),
+ description(optional_field(fields, "Description")),
+ maintainer(optional_field(fields, "Maintainer"))
{
- details::required_field(fields, name, "Package");
- required_field(fields, version, "Version");
- required_field(fields, target_triplet.value, "Architecture");
+ const std::string name = required_field(fields, "Package");
+ const triplet target_triplet = triplet::from_canonical_name(required_field(fields, "Architecture"));
+ this->spec = package_spec::from_name_and_triplet(name, target_triplet).get_or_throw();
+
{
- std::string multi_arch;
- required_field(fields, multi_arch, "Multi-Arch");
+ std::string multi_arch = required_field(fields, "Multi-Arch");
Checks::check_throw(multi_arch == "same", "Multi-Arch must be 'same' but was %s", multi_arch);
}
- optional_field(fields, description, "Description");
- std::string deps;
- optional_field(fields, deps, "Depends");
+
+ std::string deps = optional_field(fields, "Depends");
if (!deps.empty())
{
- depends.clear();
- parse_depends(deps, depends);
+ this->depends.clear();
+ this->depends = parse_depends(deps);
}
- optional_field(fields, maintainer, "Maintainer");
}
BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const triplet& target_triplet)
{
- this->name = spgh.name;
+ this->spec = package_spec::from_name_and_triplet(spgh.name, target_triplet).get_or_throw();
this->version = spgh.version;
this->description = spgh.description;
this->maintainer = spgh.maintainer;
this->depends = spgh.depends;
- this->target_triplet = target_triplet;
}
std::string BinaryParagraph::displayname() const
{
- return Strings::format("%s:%s", this->name, this->target_triplet);
+ return Strings::format("%s:%s", this->spec.name(), this->spec.target_triplet());
}
std::string BinaryParagraph::dir() const
{
- return Strings::format("%s_%s", this->name, this->target_triplet);
+ return this->spec.dir();
}
std::string BinaryParagraph::fullstem() const
{
- return Strings::format("%s_%s_%s", this->name, this->version, this->target_triplet);
+ return Strings::format("%s_%s_%s", this->spec.name(), this->version, this->spec.target_triplet());
}
std::ostream& operator<<(std::ostream& os, const BinaryParagraph& p)
{
- os << "Package: " << p.name << "\n";
+ os << "Package: " << p.spec.name() << "\n";
os << "Version: " << p.version << "\n";
if (!p.depends.empty())
{
@@ -71,7 +71,7 @@ namespace vcpkg
os << "\n";
}
- os << "Architecture: " << p.target_triplet << "\n";
+ os << "Architecture: " << p.spec.target_triplet() << "\n";
os << "Multi-Arch: same\n";
if (!p.maintainer.empty())
os << "Maintainer: " << p.maintainer << "\n";
diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp
index 7e3b0403e..374121ae9 100644
--- a/toolsrc/src/SourceParagraph.cpp
+++ b/toolsrc/src/SourceParagraph.cpp
@@ -5,17 +5,16 @@ using namespace vcpkg::details;
vcpkg::SourceParagraph::SourceParagraph() = default;
-vcpkg::SourceParagraph::SourceParagraph(const std::unordered_map<std::string, std::string>& fields)
+vcpkg::SourceParagraph::SourceParagraph(const std::unordered_map<std::string, std::string>& fields):
+ name(required_field(fields, "Source")),
+ version(required_field(fields, "Version")),
+ description(optional_field(fields, "Description")),
+ maintainer(optional_field(fields, "Maintainer"))
{
- required_field(fields, name, "Source");
- required_field(fields, version, "Version");
- optional_field(fields, description, "Description");
- std::string deps;
- optional_field(fields, deps, "Build-Depends");
+ std::string deps = optional_field(fields, "Build-Depends");
if (!deps.empty())
{
- depends.clear();
- parse_depends(deps, depends);
- }
- optional_field(fields, maintainer, "Maintainer");
+ this->depends.clear();
+ this->depends = parse_depends(deps);
+ };
}
diff --git a/toolsrc/src/StatusParagraph.cpp b/toolsrc/src/StatusParagraph.cpp
index 09a3b4d45..5aa425969 100644
--- a/toolsrc/src/StatusParagraph.cpp
+++ b/toolsrc/src/StatusParagraph.cpp
@@ -19,8 +19,7 @@ namespace vcpkg
StatusParagraph::StatusParagraph(const std::unordered_map<std::string, std::string>& fields)
: package(fields)
{
- std::string status_field;
- required_field(fields, status_field, "Status");
+ std::string status_field = required_field(fields, "Status");
auto b = status_field.begin();
auto mark = b;
diff --git a/toolsrc/src/StatusParagraphs.cpp b/toolsrc/src/StatusParagraphs.cpp
index 463e3e3b8..3e23c519a 100644
--- a/toolsrc/src/StatusParagraphs.cpp
+++ b/toolsrc/src/StatusParagraphs.cpp
@@ -13,17 +13,19 @@ namespace vcpkg
StatusParagraphs::const_iterator StatusParagraphs::find(const std::string& name, const triplet& target_triplet) const
{
- return std::find_if(begin(), end(), [&](const auto& pgh)
+ return std::find_if(begin(), end(), [&](const std::unique_ptr<StatusParagraph>& pgh)
{
- return pgh->package.name == name && pgh->package.target_triplet == target_triplet;
+ const package_spec& spec = pgh->package.spec;
+ return spec.name() == name && spec.target_triplet() == target_triplet;
});
}
StatusParagraphs::iterator StatusParagraphs::find(const std::string& name, const triplet& target_triplet)
{
- return std::find_if(begin(), end(), [&](const auto& pgh)
+ return std::find_if(begin(), end(), [&](const std::unique_ptr<StatusParagraph>& pgh)
{
- return pgh->package.name == name && pgh->package.target_triplet == target_triplet;
+ const package_spec& spec = pgh->package.spec;
+ return spec.name() == name && spec.target_triplet() == target_triplet;
});
}
@@ -41,18 +43,17 @@ namespace vcpkg
StatusParagraphs::iterator StatusParagraphs::insert(std::unique_ptr<StatusParagraph> pgh)
{
Checks::check_throw(pgh != nullptr, "Inserted null paragraph");
- auto ptr = find(pgh->package.name, pgh->package.target_triplet);
+ const package_spec& spec = pgh->package.spec;
+ auto ptr = find(spec.name(), spec.target_triplet());
if (ptr == end())
{
paragraphs.push_back(std::move(pgh));
return paragraphs.rbegin();
}
- else
- {
- // consume data from provided pgh.
- **ptr = std::move(*pgh);
- return ptr;
- }
+
+ // consume data from provided pgh.
+ **ptr = std::move(*pgh);
+ return ptr;
}
std::ostream& vcpkg::operator<<(std::ostream& os, const StatusParagraphs& l)
diff --git a/toolsrc/src/commands_cache.cpp b/toolsrc/src/commands_cache.cpp
new file mode 100644
index 000000000..0d70f0f29
--- /dev/null
+++ b/toolsrc/src/commands_cache.cpp
@@ -0,0 +1,39 @@
+#include "vcpkg_Commands.h"
+#include "vcpkg_System.h"
+#include "vcpkg_Files.h"
+#include "vcpkg.h"
+
+namespace vcpkg
+{
+ void cache_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ args.check_exact_arg_count(0);
+
+ auto begin_it = fs::directory_iterator(paths.packages);
+ auto end_it = fs::directory_iterator();
+
+ if (begin_it == end_it)
+ {
+ System::println("No packages are cached.");
+ exit(EXIT_SUCCESS);
+ }
+
+ for (; begin_it != end_it; ++begin_it)
+ {
+ const auto& path = begin_it->path();
+
+ auto file_contents = Files::get_contents(path / "CONTROL");
+ if (auto text = file_contents.get())
+ {
+ auto pghs = parse_paragraphs(*text);
+ if (pghs.size() != 1)
+ continue;
+
+ auto src = BinaryParagraph(pghs[0]);
+ System::println(src.displayname().c_str());
+ }
+ }
+
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/toolsrc/src/commands_create.cpp b/toolsrc/src/commands_create.cpp
new file mode 100644
index 000000000..d1611eb5c
--- /dev/null
+++ b/toolsrc/src/commands_create.cpp
@@ -0,0 +1,37 @@
+#include "vcpkg_Commands.h"
+#include "vcpkg_System.h"
+#include "vcpkg_Environment.h"
+#include "vcpkg_Files.h"
+#include "vcpkg_Input.h"
+
+namespace vcpkg
+{
+ void create_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ static const std::string example = create_example_string(R"###(create zlib2 http://zlib.net/zlib128.zip "zlib128-2.zip")###");
+ args.check_max_arg_count(3, example.c_str());
+ args.check_min_arg_count(2, example.c_str());
+
+ const std::string port_name = args.command_arguments.at(0);
+ Environment::ensure_utilities_on_path(paths);
+
+ // Space OR define the FILENAME with proper spacing
+ std::wstring custom_filename = L" ";
+ if (args.command_arguments.size() >= 3)
+ {
+ const std::string& zip_file_name = args.command_arguments.at(2);
+ Checks::check_exit(!Files::has_invalid_chars_for_filesystem(zip_file_name),
+ R"(Filename cannot contain invalid chars %s, but was %s)",
+ Files::FILESYSTEM_INVALID_CHARACTERS, zip_file_name);
+ custom_filename = Strings::wformat(LR"( -DFILENAME="%s" )", Strings::utf8_to_utf16(zip_file_name));
+ }
+
+ const std::wstring cmdline = Strings::wformat(LR"(cmake -DCMD=CREATE -DPORT=%s -DURL=%s%s-P "%s")",
+ Strings::utf8_to_utf16(port_name),
+ Strings::utf8_to_utf16(args.command_arguments.at(1)),
+ custom_filename,
+ paths.ports_cmake.generic_wstring());
+
+ exit(System::cmd_execute(cmdline));
+ }
+}
diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp
new file mode 100644
index 000000000..f07a15875
--- /dev/null
+++ b/toolsrc/src/commands_edit.cpp
@@ -0,0 +1,33 @@
+#include "vcpkg_Commands.h"
+#include "vcpkg_System.h"
+#include "vcpkg_Input.h"
+
+namespace vcpkg
+{
+ void edit_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ static const std::string example = create_example_string("edit zlib");
+ args.check_exact_arg_count(1, example.c_str());
+ const std::string port_name = args.command_arguments.at(0);
+
+ const fs::path portpath = paths.ports / port_name;
+
+ // Find editor
+ std::wstring env_EDITOR = System::wdupenv_str(L"EDITOR");
+ if (env_EDITOR.empty())
+ {
+ static const std::wstring CODE_EXE_PATH = LR"(C:\Program Files (x86)\Microsoft VS Code\Code.exe)";
+ if (fs::exists(CODE_EXE_PATH))
+ {
+ env_EDITOR = CODE_EXE_PATH;
+ }
+ else
+ {
+ Checks::exit_with_message("Visual Studio Code was not found and the environmental variable EDITOR is not set");
+ }
+ }
+
+ std::wstring cmdLine = Strings::wformat(LR"("%s" "%s" "%s")", env_EDITOR, portpath.native(), (portpath / "portfile.cmake").native());
+ exit(System::cmd_execute(cmdLine));
+ }
+}
diff --git a/toolsrc/src/commands_help.cpp b/toolsrc/src/commands_help.cpp
index 4e1ae9c49..194e809b1 100644
--- a/toolsrc/src/commands_help.cpp
+++ b/toolsrc/src/commands_help.cpp
@@ -6,18 +6,17 @@ namespace vcpkg
{
void version_command(const vcpkg_cmd_arguments& args)
{
- args.check_max_args(0);
+ args.check_exact_arg_count(0);
System::println("Vcpkg package management program version %s\n"
"\n"
- "Vcpkg is provided \"as-is\" without warranty of any kind, express or implied.\n"
- "All rights reserved.", vcpkg::version()
+ "See LICENSE.txt for license information.", vcpkg::version()
);
exit(EXIT_SUCCESS);
}
void help_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
{
- args.check_max_args(1);
+ args.check_max_arg_count(1);
if (args.command_arguments.empty())
{
print_usage();
@@ -37,8 +36,9 @@ namespace vcpkg
exit(EXIT_SUCCESS);
}
- void contact_command(const vcpkg_cmd_arguments& /*args*/)
+ void contact_command(const vcpkg_cmd_arguments& args)
{
+ args.check_exact_arg_count(0);
System::println("Send an email to vcpkg@microsoft.com with any feedback.");
exit(EXIT_SUCCESS);
}
diff --git a/toolsrc/src/commands_import.cpp b/toolsrc/src/commands_import.cpp
new file mode 100644
index 000000000..9cfc53d6c
--- /dev/null
+++ b/toolsrc/src/commands_import.cpp
@@ -0,0 +1,25 @@
+#include "vcpkg_Commands.h"
+#include "vcpkg.h"
+
+namespace vcpkg
+{
+ void import_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ static const std::string example = create_example_string(R"(import C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)");
+ args.check_exact_arg_count(3, example.c_str());
+
+ const fs::path control_file_path(args.command_arguments[0]);
+ const fs::path include_directory(args.command_arguments[1]);
+ const fs::path project_directory(args.command_arguments[2]);
+
+ auto pghs = get_paragraphs(control_file_path);
+ Checks::check_throw(pghs.size() == 1, "Invalid control file for package");
+
+ StatusParagraph spgh;
+ spgh.package = BinaryParagraph(pghs[0]);
+ auto& control_file_data = spgh.package;
+
+ vcpkg::binary_import(paths, include_directory, project_directory, control_file_data);
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/toolsrc/src/commands_installation.cpp b/toolsrc/src/commands_installation.cpp
index b70ab0249..6fe6aa9a1 100644
--- a/toolsrc/src/commands_installation.cpp
+++ b/toolsrc/src/commands_installation.cpp
@@ -1,13 +1,13 @@
#include "vcpkg_Commands.h"
#include "vcpkg.h"
-#include <iostream>
#include <fstream>
-#include <iomanip>
#include "vcpkg_Environment.h"
#include "metrics.h"
#include "vcpkg_Files.h"
#include "post_build_lint.h"
#include "vcpkg_System.h"
+#include "vcpkg_Dependencies.h"
+#include "vcpkg_Input.h"
namespace vcpkg
{
@@ -23,12 +23,13 @@ namespace vcpkg
static void build_internal(const package_spec& spec, const vcpkg_paths& paths, const fs::path& port_dir)
{
const fs::path ports_cmake_script_path = paths.ports_cmake;
- const std::wstring command = Strings::format(LR"("%%VS140COMNTOOLS%%..\..\VC\vcvarsall.bat" %s && cmake -DCMD=BUILD -DPORT=%s -DTARGET_TRIPLET=%s "-DCURRENT_PORT_DIR=%s/." -P "%s")",
- Strings::utf8_to_utf16(spec.target_triplet.architecture()),
- Strings::utf8_to_utf16(spec.name),
- Strings::utf8_to_utf16(spec.target_triplet.value),
- port_dir.generic_wstring(),
- ports_cmake_script_path.generic_wstring());
+ auto&& target_triplet = spec.target_triplet();
+ const std::wstring command = Strings::wformat(LR"("%%VS140COMNTOOLS%%..\..\VC\vcvarsall.bat" %s && cmake -DCMD=BUILD -DPORT=%s -DTARGET_TRIPLET=%s "-DCURRENT_PORT_DIR=%s/." -P "%s")",
+ Strings::utf8_to_utf16(target_triplet.architecture()),
+ Strings::utf8_to_utf16(spec.name()),
+ Strings::utf8_to_utf16(target_triplet.canonical_name()),
+ port_dir.generic_wstring(),
+ ports_cmake_script_path.generic_wstring());
System::Stopwatch timer;
timer.start();
@@ -38,15 +39,22 @@ namespace vcpkg
if (return_code != 0)
{
- System::println(System::color::error, "Error: build command failed");
+ System::println(System::color::error, "Error: building package %s failed", to_string(spec));
+ System::println("Please ensure sure you're using the latest portfiles with `vcpkg update`, then\n"
+ "submit an issue at https://github.com/Microsoft/vcpkg/issues including:\n"
+ " Package: %s\n"
+ " Vcpkg version: %s\n"
+ "\n"
+ "Additionally, attach any relevant sections from the log files above."
+ , to_string(spec), version());
TrackProperty("error", "build failed");
- TrackProperty("build_error", std::to_string(return_code));
+ TrackProperty("build_error", to_string(spec));
exit(EXIT_FAILURE);
}
perform_all_checks(spec, paths);
- create_binary_control_file(paths, port_dir, spec.target_triplet);
+ create_binary_control_file(paths, port_dir, target_triplet);
// const fs::path port_buildtrees_dir = paths.buildtrees / spec.name;
// delete_directory(port_buildtrees_dir);
@@ -54,33 +62,37 @@ namespace vcpkg
static void build_internal(const package_spec& spec, const vcpkg_paths& paths)
{
- return build_internal(spec, paths, paths.ports / spec.name);
+ return build_internal(spec, paths, paths.ports / spec.name());
}
void install_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
{
+ static const std::string example = create_example_string("install zlib zlib:x64-windows curl boost");
+ args.check_min_arg_count(1, example.c_str());
StatusParagraphs status_db = database_load_check(paths);
- std::vector<package_spec> specs = args.extract_package_specs_with_unmet_dependencies(paths, default_target_triplet, status_db);
- Checks::check_exit(!specs.empty(), "Specs cannot be empty");
- std::string specs_string = to_string(specs[0]);
- for (size_t i = 1; i < specs.size(); ++i)
+ std::vector<package_spec> specs = Input::check_and_get_package_specs(args.command_arguments, default_target_triplet, example.c_str());
+ Input::check_triplets(specs, paths);
+ std::vector<package_spec> install_plan = Dependencies::create_dependency_ordered_install_plan(paths, specs, status_db);
+ Checks::check_exit(!install_plan.empty(), "Install plan cannot be empty");
+ std::string specs_string = to_string(install_plan[0]);
+ for (size_t i = 1; i < install_plan.size(); ++i)
{
specs_string.push_back(',');
- specs_string.append(to_string(specs[i]));
+ specs_string.append(to_string(install_plan[i]));
}
TrackProperty("installplan", specs_string);
Environment::ensure_utilities_on_path(paths);
- for (const package_spec& spec : specs)
+ for (const package_spec& spec : install_plan)
{
- if (status_db.find_installed(spec.name, spec.target_triplet) != status_db.end())
+ if (status_db.find_installed(spec.name(), spec.target_triplet()) != status_db.end())
{
System::println(System::color::success, "Package %s is already installed", spec);
continue;
}
- fs::path package_path = find_available_package(paths, spec);
+ fs::path package_path = paths.package_dir(spec);
expected<std::string> file_contents = Files::get_contents(package_path / "CONTROL");
@@ -111,98 +123,46 @@ namespace vcpkg
exit(EXIT_SUCCESS);
}
- void search_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
- {
- args.check_max_args(1);
-
- if (args.command_arguments.size() == 1)
- {
- System::println(System::color::warning, "Search strings are not yet implemented; showing full list of packages.");
- }
-
- auto begin_it = fs::directory_iterator(paths.ports);
- auto end_it = fs::directory_iterator();
- for (; begin_it != end_it; ++begin_it)
- {
- const auto& path = begin_it->path();
-
- try
- {
- auto pghs = get_paragraphs(path / "CONTROL");
- if (pghs.empty())
- continue;
- auto srcpgh = SourceParagraph(pghs[0]);
- std::cout << std::left
- << std::setw(20) << srcpgh.name << ' '
- << std::setw(16) << srcpgh.version << ' '
- << shorten_description(srcpgh.description) << '\n';
- }
- catch (std::runtime_error const&)
- {
- }
- }
-
- System::println("\nIf your library is not listed, please open an issue at:\n"
- " https://github.com/Microsoft/vcpkg/issues");
-
- exit(EXIT_SUCCESS);
- }
-
- void cache_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)
{
- args.check_max_args(0);
+ static const std::string example = create_example_string("build zlib:x64-windows");
- auto begin_it = fs::directory_iterator(paths.packages);
- auto end_it = fs::directory_iterator();
+ // Installing multiple packages leads to unintuitive behavior if one of them depends on another.
+ // Allowing only 1 package for now.
- if (begin_it == end_it)
- {
- System::println("No packages are cached.");
- exit(EXIT_SUCCESS);
- }
+ args.check_exact_arg_count(1, example.c_str());
+ StatusParagraphs status_db = database_load_check(paths);
- for (; begin_it != end_it; ++begin_it)
+ const package_spec spec = Input::check_and_get_package_spec(args.command_arguments.at(0), default_target_triplet, example.c_str());
+ Input::check_triplet(spec.target_triplet(), paths);
+ std::unordered_set<package_spec> unmet_dependencies = Dependencies::find_unmet_dependencies(paths, spec, status_db);
+ if (!unmet_dependencies.empty())
{
- const auto& path = begin_it->path();
-
- auto file_contents = Files::get_contents(path / "CONTROL");
- if (auto text = file_contents.get())
+ System::println(System::color::error, "The build command requires all dependencies to be already installed.");
+ System::println("The following dependencies are missing:");
+ System::println("");
+ for (const package_spec& p : unmet_dependencies)
{
- auto pghs = parse_paragraphs(*text);
- if (pghs.size() != 1)
- continue;
-
- auto src = BinaryParagraph(pghs[0]);
- System::println(src.displayname().c_str());
+ System::println(" %s", to_string(p));
}
+ System::println("");
+ exit(EXIT_FAILURE);
}
- exit(EXIT_SUCCESS);
- }
-
- void build_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
- {
- std::vector<package_spec> specs = args.parse_all_arguments_as_package_specs(default_target_triplet);
Environment::ensure_utilities_on_path(paths);
- for (const package_spec& spec : specs)
- {
- build_internal(spec, paths);
- }
+ build_internal(spec, paths);
exit(EXIT_SUCCESS);
}
void build_external_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
{
- if (args.command_arguments.size() != 2)
- {
- System::println(System::color::error, "Error: buildexternal requires the package name and the directory containing the CONTROL file");
- print_example(R"(buildexternal mylib C:\path\to\mylib\)");
- exit(EXIT_FAILURE);
- }
+ static const std::string example = create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)");
+ args.check_exact_arg_count(2, example.c_str());
- expected<package_spec> current_spec = vcpkg::parse(args.command_arguments[0], default_target_triplet);
+ expected<package_spec> current_spec = package_spec::from_string(args.command_arguments[0], default_target_triplet);
if (auto spec = current_spec.get())
{
+ Input::check_triplet(spec->target_triplet(), paths);
Environment::ensure_utilities_on_path(paths);
const fs::path port_dir = args.command_arguments.at(1);
build_internal(*spec, paths, port_dir);
diff --git a/toolsrc/src/commands_integration.cpp b/toolsrc/src/commands_integration.cpp
index 178d40e83..6a11d6ec4 100644
--- a/toolsrc/src/commands_integration.cpp
+++ b/toolsrc/src/commands_integration.cpp
@@ -195,7 +195,7 @@ namespace vcpkg
const fs::path sys_src_path = tmp_dir / "vcpkg.system.targets";
std::ofstream(sys_src_path) << create_system_targets_shortcut();
- const std::string param = Strings::format(R"(/c XCOPY "%s" "%s*" /Y > nul)", sys_src_path.string(), system_wide_targets_file.string());
+ const std::string param = Strings::format(R"(/c mkdir "%s" & copy "%s" "%s" /Y > nul)", system_wide_targets_file.parent_path().string(), sys_src_path.string(), system_wide_targets_file.string());
elevation_prompt_user_choice user_choice = elevated_cmd_execute(param);
switch (user_choice)
{
@@ -238,7 +238,7 @@ namespace vcpkg
exit(EXIT_SUCCESS);
}
- const std::wstring cmd_line = Strings::format(LR"(DEL "%s")", get_appdata_targets_path().native());
+ const std::wstring cmd_line = Strings::wformat(LR"(DEL "%s")", get_appdata_targets_path().native());
const int exit_code = System::cmd_execute(cmd_line);
if (exit_code)
{
@@ -269,7 +269,7 @@ namespace vcpkg
std::ofstream(nuspec_file_path) << create_nuspec_file(paths.root, nuget_id, nupkg_version);
// Using all forward slashes for the command line
- const std::wstring cmd_line = Strings::format(LR"(nuget.exe pack -OutputDirectory "%s" "%s" > nul)", buildsystems_dir.native(), nuspec_file_path.native());
+ const std::wstring cmd_line = Strings::wformat(LR"(nuget.exe pack -OutputDirectory "%s" "%s" > nul)", buildsystems_dir.native(), nuspec_file_path.native());
const int exit_code = System::cmd_execute(cmd_line);
@@ -297,13 +297,9 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console
void integrate_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
{
- if (args.command_arguments.size() != 1)
- {
- std::cout << "Commands:\n" <<
- INTEGRATE_COMMAND_HELPSTRING <<
- "\n";
- exit(EXIT_FAILURE);
- }
+ static const std::string example = Strings::format("Commands:\n"
+ "%s", INTEGRATE_COMMAND_HELPSTRING);
+ args.check_exact_arg_count(1, example.c_str());
if (args.command_arguments[0] == "install")
{
diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp
new file mode 100644
index 000000000..194e4b435
--- /dev/null
+++ b/toolsrc/src/commands_list.cpp
@@ -0,0 +1,32 @@
+#include "vcpkg_Commands.h"
+#include "vcpkg.h"
+#include "vcpkg_System.h"
+
+namespace vcpkg
+{
+ void list_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ args.check_exact_arg_count(0);
+
+ std::vector<std::string> packages_output;
+ for (auto&& pgh : database_load_check(paths))
+ {
+ if (pgh->state == install_state_t::not_installed && pgh->want == want_t::purge)
+ continue;
+ packages_output.push_back(Strings::format("%-27s %-16s %s",
+ pgh->package.displayname(),
+ pgh->package.version,
+ shorten_description(pgh->package.description)));
+ }
+ std::sort(packages_output.begin(), packages_output.end());
+ for (auto&& package : packages_output)
+ {
+ System::println(package.c_str());
+ }
+ if (packages_output.empty())
+ {
+ System::println("No packages are installed. Did you mean `search`?");
+ }
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/toolsrc/src/commands_other.cpp b/toolsrc/src/commands_other.cpp
index c7dcc2586..07549a437 100644
--- a/toolsrc/src/commands_other.cpp
+++ b/toolsrc/src/commands_other.cpp
@@ -1,16 +1,13 @@
#include "vcpkg_Commands.h"
-#include <iostream>
-#include <unordered_set>
-#include "vcpkg_Environment.h"
-#include "vcpkg.h"
#include "vcpkg_System.h"
-#include "vcpkg_Files.h"
+#include "vcpkg.h"
namespace vcpkg
{
void print_usage()
{
- std::cout << "Commands:\n"
+ System::println(
+ "Commands:\n"
" vcpkg search [pat] Search for packages available to be built\n"
" vcpkg install <pkg> Install a package\n"
" vcpkg remove <pkg> Uninstall a package. \n"
@@ -18,9 +15,9 @@ namespace vcpkg
" vcpkg list List installed packages\n"
" vcpkg update Display list of packages for updating\n"
"\n"
- << INTEGRATE_COMMAND_HELPSTRING <<
+ "%s" // Integration help
"\n"
- " vcpkg edit <pkg> Open up a port for editing (uses %EDITOR%, default 'code')\n"
+ " vcpkg edit <pkg> Open up a port for editing (uses %%EDITOR%%, default 'code')\n"
" vcpkg import <pkg> Import a pre-built library\n"
" vcpkg create <pkg> <url>\n"
" [archivename] Create a new package\n"
@@ -35,215 +32,25 @@ namespace vcpkg
//"\n"
"Options:\n"
" --triplet <t> Specify the target architecture triplet.\n"
- " (default: x86-windows, see 'vcpkg help triplet')\n"
+ " (default: %%VCPKG_DEFAULT_TRIPLET%%, see 'vcpkg help triplet')\n"
"\n"
" --vcpkg-root <path> Specify the vcpkg root directory\n"
- " (default: %VCPKG_ROOT%)\n"
+ " (default: %%VCPKG_ROOT%%)\n"
"\n"
"For more help (including examples) see the accompanying README.md."
- "\n";
+ , INTEGRATE_COMMAND_HELPSTRING);
}
- void print_example(const char* command_and_arguments)
+ std::string create_example_string(const char* command_and_arguments)
{
- std::cout <<
- "Example:\n"
- " vcpkg " << command_and_arguments << "\n";
+ std::string cs = Strings::format("Example:\n"
+ " vcpkg %s", command_and_arguments);
+ return cs;
}
- void update_command(const vcpkg_cmd_arguments& /*args*/, const vcpkg_paths& paths)
- {
- auto status_db = database_load_check(paths);
-
- std::unordered_map<std::string, std::string> src_names_to_versions;
-
- auto begin_it = fs::directory_iterator(paths.ports);
- auto end_it = fs::directory_iterator();
- for (; begin_it != end_it; ++begin_it)
- {
- const auto& path = begin_it->path();
- try
- {
- auto pghs = get_paragraphs(path / "CONTROL");
- if (pghs.empty())
- continue;
- auto srcpgh = SourceParagraph(pghs[0]);
- src_names_to_versions.emplace(srcpgh.name, srcpgh.version);
- }
- catch (std::runtime_error const&)
- {
- }
- }
-
- std::string packages_list;
-
- std::vector<std::string> packages_output;
- for (auto&& pgh : database_load_check(paths))
- {
- if (pgh->state == install_state_t::not_installed && pgh->want == want_t::purge)
- continue;
- auto it = src_names_to_versions.find(pgh->package.name);
- if (it == src_names_to_versions.end())
- {
- // Package was not installed from portfile
- continue;
- }
- if (it->second != pgh->package.version)
- {
- packages_output.push_back(Strings::format("%-27s %s -> %s",
- pgh->package.displayname(),
- pgh->package.version,
- it->second));
- packages_list.append(" " + pgh->package.displayname());
- }
- }
- std::sort(packages_output.begin(), packages_output.end());
- if (packages_output.empty())
- {
- System::println("No packages need updating.");
- }
- else
- {
- System::println("The following packages differ from their port versions:");
- for (auto&& package : packages_output)
- {
- System::println(" %s", package.c_str());
- }
- System::println("\nTo update these packages, run\n vcpkg remove --purge <pkgs>...\n vcpkg install <pkgs>...");
- }
-
- auto version_file = Files::get_contents(paths.root / "toolsrc" / "VERSION.txt");
- if (auto version_contents = version_file.get())
- {
- int maj1, min1, rev1;
- auto num1 = sscanf_s(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1);
-
- int maj2, min2, rev2;
- auto num2 = sscanf_s(version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2);
-
- if (num1 == 3 && num2 == 3)
- {
- if (maj1 != maj2 || min1 != min2 || rev1 != rev2)
- {
- System::println("Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use scripts\\bootstrap.ps1 to update.",
- maj2, min2, rev2,
- maj1, min1, rev1);
- }
- }
- }
-
- exit(EXIT_SUCCESS);
- }
-
- void edit_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
- {
- static auto example = "edit zlib";
- args.check_max_args(1, example);
- package_spec spec = args.parse_all_arguments_as_package_specs(default_target_triplet, example).at(0);
-
- // Find editor
- std::wstring env_EDITOR = System::wdupenv_str(L"EDITOR");
- if (env_EDITOR.empty())
- env_EDITOR = LR"(C:\Program Files (x86)\Microsoft VS Code\Code.exe)";
-
- auto portpath = paths.ports / spec.name;
- std::wstring cmdLine = Strings::format(LR"("%s" "%s" "%s")", env_EDITOR, portpath.native(), (portpath / "portfile.cmake").native());
- exit(System::cmd_execute(cmdLine));
- }
-
- void create_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
- {
- args.check_max_args(3);
- package_spec spec = args.parse_all_arguments_as_package_specs(default_target_triplet).at(0);
- if (args.command_arguments.size() < 2)
- {
- System::println(System::color::error, "Error: create requires the archive's URL as the second argument.");
- print_usage();
- exit(EXIT_FAILURE);
- }
- Environment::ensure_utilities_on_path(paths);
-
- // Space OR define the FILENAME with proper spacing
- std::wstring custom_filename = L" ";
- if (args.command_arguments.size() >= 3)
- {
- custom_filename = Strings::format(L" -DFILENAME=%s ", Strings::utf8_to_utf16(args.command_arguments.at(2)));
- }
-
- const std::wstring cmdline = Strings::format(LR"(cmake -DCMD=SCAFFOLD -DPORT=%s -DTARGET_TRIPLET=%s -DURL=%s%s-P "%s")",
- Strings::utf8_to_utf16(spec.name),
- Strings::utf8_to_utf16(spec.target_triplet.value),
- Strings::utf8_to_utf16(args.command_arguments.at(1)),
- custom_filename,
- paths.ports_cmake.generic_wstring());
-
- exit(System::cmd_execute(cmdline));
- }
-
- void list_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
- {
- args.check_max_args(0);
-
- std::vector<std::string> packages_output;
- for (auto&& pgh : database_load_check(paths))
- {
- if (pgh->state == install_state_t::not_installed && pgh->want == want_t::purge)
- continue;
- packages_output.push_back(Strings::format("%-27s %-16s %s",
- pgh->package.displayname(),
- pgh->package.version,
- shorten_description(pgh->package.description)));
- }
- std::sort(packages_output.begin(), packages_output.end());
- for (auto&& package : packages_output)
- {
- System::println(package.c_str());
- }
- if (packages_output.empty())
- {
- System::println("No packages are installed. Did you mean `search`?");
- }
- exit(EXIT_SUCCESS);
- }
-
- void import_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
- {
- if (args.command_arguments.size() != 3)
- {
- System::println(System::color::error, "Error: %s requires 3 parameters", args.command);
- print_example(Strings::format(R"(%s C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)", args.command).c_str());
- exit(EXIT_FAILURE);
- }
-
- const fs::path control_file_path(args.command_arguments[0]);
- const fs::path include_directory(args.command_arguments[1]);
- const fs::path project_directory(args.command_arguments[2]);
-
- auto pghs = get_paragraphs(control_file_path);
- Checks::check_throw(pghs.size() == 1, "Invalid control file for package");
-
- StatusParagraph spgh;
- spgh.package = BinaryParagraph(pghs[0]);
- auto& control_file_data = spgh.package;
-
- vcpkg::binary_import(paths, include_directory, project_directory, control_file_data);
- exit(EXIT_SUCCESS);
- }
-
- void owns_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ void print_example(const char* command_and_arguments)
{
- args.check_max_args(1);
- if (args.command_arguments.size() == 0)
- {
- System::println(System::color::error, "Error: owns requires a pattern to search for as the first argument.");
- std::cout <<
- "example:\n"
- " vcpkg owns .dll\n";
- exit(EXIT_FAILURE);
- }
- StatusParagraphs status_db = database_load_check(paths);
- search_file(paths, args.command_arguments[0], status_db);
- exit(EXIT_SUCCESS);
+ System::println(create_example_string(command_and_arguments).c_str());
}
void internal_test_command(const vcpkg_cmd_arguments& /*args*/, const vcpkg_paths& /*paths*/)
@@ -259,8 +66,6 @@ namespace vcpkg
{"install", install_command},
{"remove", remove_command},
{"build", build_command},
- {"edit", edit_command},
- {"create", create_command},
{"build_external", build_external_command}
};
return t;
@@ -275,6 +80,8 @@ namespace vcpkg
{"integrate", integrate_command},
{"owns", owns_command},
{"update", update_command},
+ {"edit", edit_command},
+ {"create", create_command},
{"import", import_command},
{"cache", cache_command},
{"internal_test", internal_test_command},
diff --git a/toolsrc/src/commands_owns.cpp b/toolsrc/src/commands_owns.cpp
new file mode 100644
index 000000000..b3dab2e44
--- /dev/null
+++ b/toolsrc/src/commands_owns.cpp
@@ -0,0 +1,16 @@
+#include "vcpkg_Commands.h"
+#include "vcpkg_System.h"
+#include "vcpkg.h"
+
+namespace vcpkg
+{
+ void owns_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ static const std::string example = Strings::format("The argument should be a pattern to search for. %s", create_example_string("owns zlib.dll"));
+ args.check_exact_arg_count(1, example.c_str());
+
+ StatusParagraphs status_db = database_load_check(paths);
+ search_file(paths, args.command_arguments[0], status_db);
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp
index f5315ccb1..5bb9ecc96 100644
--- a/toolsrc/src/commands_remove.cpp
+++ b/toolsrc/src/commands_remove.cpp
@@ -1,6 +1,7 @@
#include "vcpkg_Commands.h"
#include "vcpkg.h"
#include "vcpkg_System.h"
+#include "vcpkg_Input.h"
namespace vcpkg
{
@@ -22,10 +23,14 @@ namespace vcpkg
void remove_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
{
+ static const std::string example = create_example_string("remove zlib zlib:x64-windows curl boost");
+ args.check_min_arg_count(1, example.c_str());
+
const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({OPTION_PURGE});
auto status_db = database_load_check(paths);
- std::vector<package_spec> specs = args.parse_all_arguments_as_package_specs(default_target_triplet);
+ std::vector<package_spec> specs = Input::check_and_get_package_specs(args.command_arguments, default_target_triplet, example.c_str());
+ Input::check_triplets(specs, paths);
bool alsoRemoveFolderFromPackages = options.find(OPTION_PURGE) != options.end();
for (const package_spec& spec : specs)
diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp
new file mode 100644
index 000000000..c90538e86
--- /dev/null
+++ b/toolsrc/src/commands_search.cpp
@@ -0,0 +1,64 @@
+#include "vcpkg_Commands.h"
+#include "vcpkg_System.h"
+#include "vcpkg.h"
+#include <iostream>
+#include <iomanip>
+
+namespace fs = std::tr2::sys;
+
+namespace vcpkg
+{
+ template <class Pred>
+ static void do_print(const vcpkg_paths& paths, Pred predicate)
+ {
+ for (auto it = fs::directory_iterator(paths.ports); it != fs::directory_iterator(); ++it)
+ {
+ const fs::path& path = it->path();
+
+ try
+ {
+ auto pghs = get_paragraphs(path / "CONTROL");
+ if (pghs.empty())
+ continue;
+ auto srcpgh = SourceParagraph(pghs[0]);
+
+ if (predicate(srcpgh.name))
+ {
+ std::cout << std::left
+ << std::setw(20) << srcpgh.name << ' '
+ << std::setw(16) << srcpgh.version << ' '
+ << shorten_description(srcpgh.description) << '\n';
+ }
+ }
+ catch (std::runtime_error const&)
+ {
+ }
+ }
+ }
+
+ void search_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ static const std::string example = Strings::format("The argument should be a substring to search for, or no argument to display all libraries.\n%s", create_example_string("search png"));
+ args.check_max_arg_count(1, example.c_str());
+
+ if (args.command_arguments.size() == 0)
+ {
+ do_print(paths, [](std::string&) -> bool
+ {
+ return true;
+ });
+ exit(EXIT_SUCCESS);
+ }
+
+ // At this point there is 1 argument
+ do_print(paths, [&](std::string& port_name) -> bool
+ {
+ return Strings::case_insensitive_ascii_find(port_name, args.command_arguments[0]) != port_name.end();
+ });
+
+ System::println("\nIf your library is not listed, please open an issue at:\n"
+ " https://github.com/Microsoft/vcpkg/issues");
+
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp
new file mode 100644
index 000000000..5d531ef39
--- /dev/null
+++ b/toolsrc/src/commands_update.cpp
@@ -0,0 +1,94 @@
+#include "vcpkg_Commands.h"
+#include "vcpkg.h"
+#include "vcpkg_System.h"
+#include "vcpkg_Files.h"
+
+namespace vcpkg
+{
+ void update_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ args.check_exact_arg_count(0);
+ System::println("Using local portfile versions. To update the local portfiles, use `git pull`.");
+
+ auto status_db = database_load_check(paths);
+
+ std::unordered_map<std::string, std::string> src_names_to_versions;
+
+ auto begin_it = fs::directory_iterator(paths.ports);
+ auto end_it = fs::directory_iterator();
+ for (; begin_it != end_it; ++begin_it)
+ {
+ const auto& path = begin_it->path();
+ try
+ {
+ auto pghs = get_paragraphs(path / "CONTROL");
+ if (pghs.empty())
+ continue;
+ auto srcpgh = SourceParagraph(pghs[0]);
+ src_names_to_versions.emplace(srcpgh.name, srcpgh.version);
+ }
+ catch (std::runtime_error const&)
+ {
+ }
+ }
+
+ std::string packages_list;
+
+ std::vector<std::string> packages_output;
+ for (auto&& pgh : database_load_check(paths))
+ {
+ if (pgh->state == install_state_t::not_installed && pgh->want == want_t::purge)
+ continue;
+ auto it = src_names_to_versions.find(pgh->package.spec.name());
+ if (it == src_names_to_versions.end())
+ {
+ // Package was not installed from portfile
+ continue;
+ }
+ if (it->second != pgh->package.version)
+ {
+ packages_output.push_back(Strings::format("%-27s %s -> %s",
+ pgh->package.displayname(),
+ pgh->package.version,
+ it->second));
+ packages_list.append(" " + pgh->package.displayname());
+ }
+ }
+ std::sort(packages_output.begin(), packages_output.end());
+ if (packages_output.empty())
+ {
+ System::println("No packages need updating.");
+ }
+ else
+ {
+ System::println("The following packages differ from their port versions:");
+ for (auto&& package : packages_output)
+ {
+ System::println(" %s", package.c_str());
+ }
+ System::println("\nTo update these packages, run\n vcpkg remove --purge <pkgs>...\n vcpkg install <pkgs>...");
+ }
+
+ auto version_file = Files::get_contents(paths.root / "toolsrc" / "VERSION.txt");
+ if (auto version_contents = version_file.get())
+ {
+ int maj1, min1, rev1;
+ auto num1 = sscanf_s(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1);
+
+ int maj2, min2, rev2;
+ auto num2 = sscanf_s(version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2);
+
+ if (num1 == 3 && num2 == 3)
+ {
+ if (maj1 != maj2 || min1 != min2 || rev1 != rev2)
+ {
+ System::println("Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use scripts\\bootstrap.ps1 to update.",
+ maj2, min2, rev2,
+ maj1, min1, rev1);
+ }
+ }
+ }
+
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/toolsrc/src/lib.cpp b/toolsrc/src/lib.cpp
index 2a3b95182..45b73ee07 100644
--- a/toolsrc/src/lib.cpp
+++ b/toolsrc/src/lib.cpp
@@ -133,26 +133,6 @@ static std::string get_fullpkgname_from_listfile(const fs::path& path)
return ret;
}
-fs::path vcpkg::control_file_for_package(const fs::path& package)
-{
- return package / "CONTROL";
-}
-
-fs::path vcpkg::find_available_package(const vcpkg_paths& paths, const package_spec& spec)
-{
- return paths.packages / Strings::format("%s_%s", spec.name, spec.target_triplet);
-}
-
-fs::path vcpkg::find_available_port_file(const vcpkg_paths& paths, const package_spec& spec)
-{
- return paths.ports / spec.name;
-}
-
-static fs::path prefix_path_for_package(const vcpkg_paths& paths, const BinaryParagraph& pgh)
-{
- return find_available_package(paths, {pgh.name, pgh.target_triplet});
-}
-
static void write_update(const vcpkg_paths& paths, const StatusParagraph& p)
{
static int update_id = 0;
@@ -169,12 +149,14 @@ static void install_and_write_listfile(const vcpkg_paths& paths, const BinaryPar
{
std::fstream listfile(listfile_path(paths, bpgh), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
- auto package_prefix_path = prefix_path_for_package(paths, bpgh);
+ auto package_prefix_path = paths.package_dir(bpgh.spec);
auto prefix_length = package_prefix_path.native().size();
+ const triplet& target_triplet = bpgh.spec.target_triplet();
+ const std::string& target_triplet_as_string = target_triplet.canonical_name();
std::error_code ec;
- fs::create_directory(paths.installed / bpgh.target_triplet.value, ec);
- listfile << bpgh.target_triplet << "\n";
+ fs::create_directory(paths.installed / target_triplet_as_string, ec);
+ listfile << target_triplet << "\n";
for (auto it = fs::recursive_directory_iterator(package_prefix_path); it != fs::recursive_directory_iterator(); ++it)
{
@@ -186,12 +168,12 @@ static void install_and_write_listfile(const vcpkg_paths& paths, const BinaryPar
}
auto suffix = it->path().generic_u8string().substr(prefix_length + 1);
- auto target = paths.installed / bpgh.target_triplet.value / suffix;
+ auto target = paths.installed / target_triplet_as_string / suffix;
auto status = it->status(ec);
if (ec)
{
- System::println(System::color::error, "failed: %s", ec.message());
+ System::println(System::color::error, "failed: %s: %s", it->path().u8string(), ec.message());
continue;
}
if (fs::is_directory(status))
@@ -199,26 +181,26 @@ static void install_and_write_listfile(const vcpkg_paths& paths, const BinaryPar
fs::create_directory(target, ec);
if (ec)
{
- System::println(System::color::error, "failed: %s", ec.message());
+ System::println(System::color::error, "failed: %s: %s", target.u8string(), ec.message());
}
- listfile << bpgh.target_triplet << "/" << suffix << "\n";
+ listfile << target_triplet << "/" << suffix << "\n";
}
else if (fs::is_regular_file(status))
{
fs::copy_file(*it, target, ec);
if (ec)
{
- System::println(System::color::error, "failed: %s", ec.message());
+ System::println(System::color::error, "failed: %s: %s", target.u8string(), ec.message());
}
- listfile << bpgh.target_triplet << "/" << suffix << "\n";
+ listfile << target_triplet << "/" << suffix << "\n";
}
else if (!fs::status_known(status))
{
- std::cout << "unknown status: " << *it << "\n";
+ System::println(System::color::error, "failed: %s: unknown status", it->path().u8string());
}
else
- std::cout << "warning: file does not exist: " << *it << "\n";
+ System::println(System::color::error, "failed: %s: cannot handle file type", it->path().u8string());
}
listfile.close();
@@ -228,35 +210,40 @@ static void install_and_write_listfile(const vcpkg_paths& paths, const BinaryPar
std::vector<std::string> vcpkg::get_unmet_package_dependencies(const vcpkg_paths& paths, const package_spec& spec, const StatusParagraphs& status_db)
{
std::vector<std::unordered_map<std::string, std::string>> pghs;
- const fs::path packages_dir_control_file_path = find_available_package(paths, spec) / "CONTROL";
+ {
+ const fs::path packages_dir_control_file_path = paths.package_dir(spec) / "CONTROL";
- if (fs::exists(packages_dir_control_file_path))
+ auto control_contents_maybe = Files::get_contents(packages_dir_control_file_path);
+ if (auto control_contents = control_contents_maybe.get())
+ {
+ try
+ {
+ pghs = parse_paragraphs(*control_contents);
+ }
+ catch (std::runtime_error)
+ {
+ }
+ Checks::check_exit(pghs.size() == 1, "Invalid control file at %s", packages_dir_control_file_path.string());
+ return BinaryParagraph(pghs[0]).depends;
+ }
+ }
+
+ const fs::path ports_dir_control_file_path = paths.port_dir(spec) / "CONTROL";
+ auto control_contents_maybe = Files::get_contents(ports_dir_control_file_path);
+ if (auto control_contents = control_contents_maybe.get())
{
try
{
- pghs = get_paragraphs(packages_dir_control_file_path);
+ pghs = parse_paragraphs(*control_contents);
}
catch (std::runtime_error)
{
- // ??
}
-
- Checks::check_throw(pghs.size() == 1, "Invalid control file for package");
- return BinaryParagraph(pghs[0]).depends;
+ Checks::check_exit(pghs.size() == 1, "Invalid control file at %s", ports_dir_control_file_path.string());
+ return SourceParagraph(pghs[0]).depends;
}
- const fs::path ports_dir_control_file_path = find_available_port_file(paths, spec) / "CONTROL";
- try
- {
- pghs = get_paragraphs(ports_dir_control_file_path);
- }
- catch (std::runtime_error)
- {
- // ??
- }
-
- Checks::check_exit(pghs.size() == 1, "Invalid control file for package %s", spec);
- return SourceParagraph(pghs[0]).depends;
+ Checks::exit_with_message("Could not find package named %s", spec);
}
void vcpkg::install_package(const vcpkg_paths& paths, const BinaryParagraph& binary_paragraph, StatusParagraphs& status_db)
@@ -267,7 +254,7 @@ void vcpkg::install_package(const vcpkg_paths& paths, const BinaryParagraph& bin
spgh.state = install_state_t::half_installed;
for (const std::string& dependency : spgh.package.depends)
{
- if (status_db.find_installed(dependency, spgh.package.target_triplet) == status_db.end())
+ if (status_db.find_installed(dependency, spgh.package.spec.target_triplet()) == status_db.end())
{
std::abort();
}
@@ -307,12 +294,12 @@ static deinstall_plan deinstall_package_plan(
{
if (inst_pkg->want != want_t::install)
continue;
- if (inst_pkg->package.target_triplet != pkg.target_triplet)
+ if (inst_pkg->package.spec.target_triplet() != pkg.spec.target_triplet())
continue;
const auto& deps = inst_pkg->package.depends;
- if (std::find(deps.begin(), deps.end(), pkg.name) != deps.end())
+ if (std::find(deps.begin(), deps.end(), pkg.spec.name()) != deps.end())
{
dependencies_out.push_back(inst_pkg.get());
}
@@ -326,7 +313,7 @@ static deinstall_plan deinstall_package_plan(
void vcpkg::deinstall_package(const vcpkg_paths& paths, const package_spec& spec, StatusParagraphs& status_db)
{
- auto package_it = status_db.find(spec.name, spec.target_triplet);
+ auto package_it = status_db.find(spec.name(), spec.target_triplet());
if (package_it == status_db.end())
{
System::println(System::color::success, "Package %s is not installed", spec);
@@ -389,16 +376,16 @@ void vcpkg::deinstall_package(const vcpkg_paths& paths, const package_spec& spec
fs::remove(target, ec);
if (ec)
{
- System::println(System::color::error, "failed: %s", ec.message());
+ System::println(System::color::error, "failed: %s: %s", target.u8string(), ec.message());
}
}
else if (!fs::status_known(status))
{
- System::println(System::color::warning, "Warning: unknown status: %s", target.string());
+ System::println(System::color::warning, "Warning: unknown status: %s", target.u8string());
}
else
{
- System::println(System::color::warning, "Warning: ???: %s", target.string());
+ System::println(System::color::warning, "Warning: %s: cannot handle file type", target.u8string());
}
}
@@ -515,7 +502,7 @@ namespace
void vcpkg::binary_import(const vcpkg_paths& paths, const fs::path& include_directory, const fs::path& project_directory, const BinaryParagraph& control_file_data)
{
- fs::path library_destination_path = prefix_path_for_package(paths, control_file_data);
+ fs::path library_destination_path = paths.package_dir(control_file_data.spec);
fs::create_directory(library_destination_path);
place_library_files_in(include_directory, project_directory, library_destination_path);
diff --git a/toolsrc/src/main.cpp b/toolsrc/src/main.cpp
index d3fb855d1..f3d68f5dd 100644
--- a/toolsrc/src/main.cpp
+++ b/toolsrc/src/main.cpp
@@ -11,6 +11,7 @@
#include <Shlobj.h>
#include "vcpkg_Files.h"
#include "vcpkg_System.h"
+#include "vcpkg_Input.h"
using namespace vcpkg;
@@ -23,21 +24,6 @@ void invalid_command(const std::string& cmd)
exit(EXIT_FAILURE);
}
-static fs::path find_file_recursively_up(const fs::path& starting_dir, const std::string& filename)
-{
- fs::path current_dir = starting_dir;
- for (; !current_dir.empty(); current_dir = current_dir.parent_path())
- {
- const fs::path candidate = current_dir / filename;
- if (fs::exists(candidate))
- {
- break;
- }
- }
-
- return current_dir;
-}
-
static void inner(const vcpkg_cmd_arguments& args)
{
TrackProperty("command", args.command);
@@ -67,7 +53,7 @@ static void inner(const vcpkg_cmd_arguments& args)
}
else
{
- vcpkg_root_dir = find_file_recursively_up(fs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root");
+ vcpkg_root_dir = Files::find_file_recursively_up(fs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root");
}
}
@@ -84,32 +70,26 @@ static void inner(const vcpkg_cmd_arguments& args)
return command_function(args, paths);
}
- triplet default_target_triplet = triplet::X86_WINDOWS;
-
+ triplet default_target_triplet;
if (args.target_triplet != nullptr)
{
- const std::string& target_triplet = *args.target_triplet;
-
- auto it = fs::directory_iterator(paths.triplets);
- for (; it != fs::directory_iterator(); ++it)
+ default_target_triplet = triplet::from_canonical_name(*args.target_triplet);
+ }
+ else
+ {
+ const auto vcpkg_default_triplet_env = System::wdupenv_str(L"VCPKG_DEFAULT_TRIPLET");
+ if (!vcpkg_default_triplet_env.empty())
{
- std::string triplet_file_name = it->path().stem().generic_u8string();
- if (target_triplet == triplet_file_name) // TODO: fuzzy compare
- {
- default_target_triplet = {triplet_file_name};
- break;
- }
+ default_target_triplet = triplet::from_canonical_name(Strings::utf16_to_utf8(vcpkg_default_triplet_env));
}
-
- if (it == fs::directory_iterator())
+ else
{
- System::println(System::color::error, "Error: invalid triplet: %s", target_triplet);
- TrackProperty("error", "invalid triplet: " + target_triplet);
- help_topic_valid_triplet(paths);
- exit(EXIT_FAILURE);
+ default_target_triplet = triplet::X86_WINDOWS;
}
}
+ Input::check_triplet(default_target_triplet, paths);
+
if (auto command_function = find_command(args.command, get_available_commands_type_a()))
{
return command_function(args, paths, default_target_triplet);
diff --git a/toolsrc/src/metrics.cpp b/toolsrc/src/metrics.cpp
index 610c71ed1..ada065fd6 100644
--- a/toolsrc/src/metrics.cpp
+++ b/toolsrc/src/metrics.cpp
@@ -419,7 +419,7 @@ true
const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + GenerateRandomUUID() + ".txt");
std::ofstream(vcpkg_metrics_txt_path) << payload;
- const std::wstring cmdLine = Strings::format(L"start %s %s", temp_folder_path_exe.native(), vcpkg_metrics_txt_path.native());
+ const std::wstring cmdLine = Strings::wformat(L"start %s %s", temp_folder_path_exe.native(), vcpkg_metrics_txt_path.native());
System::cmd_execute(cmdLine);
}
}
diff --git a/toolsrc/src/package_spec.cpp b/toolsrc/src/package_spec.cpp
index ece5f91e9..86d4393bd 100644
--- a/toolsrc/src/package_spec.cpp
+++ b/toolsrc/src/package_spec.cpp
@@ -1,32 +1,63 @@
#include "package_spec.h"
+#include <algorithm>
namespace vcpkg
{
- expected<package_spec> parse(const std::string& spec, const triplet& default_target_triplet)
+ static bool is_valid_package_spec_char(char c)
{
- auto pos = spec.find(':');
+ return (c == '-') || isdigit(c) || (isalpha(c) && islower(c));
+ }
+
+ expected<package_spec> package_spec::from_string(const std::string& spec_as_string, const triplet& default_target_triplet)
+ {
+ auto pos = spec_as_string.find(':');
if (pos == std::string::npos)
{
- return package_spec{spec, default_target_triplet};
+ return from_name_and_triplet(spec_as_string, default_target_triplet);
}
- auto pos2 = spec.find(':', pos + 1);
+ auto pos2 = spec_as_string.find(':', pos + 1);
if (pos2 != std::string::npos)
{
- return std::error_code(package_spec_parse_result::too_many_colons);
+ return std::error_code(package_spec_parse_result::TOO_MANY_COLONS);
}
- return package_spec{spec.substr(0, pos), spec.substr(pos + 1)};
+ const std::string name = spec_as_string.substr(0, pos);
+ const triplet target_triplet = triplet::from_canonical_name(spec_as_string.substr(pos + 1));
+ return from_name_and_triplet(name, target_triplet);
+ }
+
+ expected<package_spec> package_spec::from_name_and_triplet(const std::string& name, const triplet& target_triplet)
+ {
+ if (std::find_if_not(name.cbegin(), name.cend(), is_valid_package_spec_char) != name.end())
+ {
+ return std::error_code(package_spec_parse_result::INVALID_CHARACTERS);
+ }
+
+ package_spec p;
+ p.m_name = name;
+ p.m_target_triplet = target_triplet;
+ return p;
+ }
+
+ const std::string& package_spec::name() const
+ {
+ return this->m_name;
+ }
+
+ const triplet& package_spec::target_triplet() const
+ {
+ return this->m_target_triplet;
}
std::string package_spec::dir() const
{
- return Strings::format("%s_%s", this->name, this->target_triplet);
+ return Strings::format("%s_%s", this->m_name, this->m_target_triplet);
}
std::string to_string(const package_spec& spec)
{
- return Strings::format("%s:%s", spec.name, spec.target_triplet);
+ return Strings::format("%s:%s", spec.name(), spec.target_triplet());
}
std::string to_printf_arg(const package_spec& spec)
@@ -36,7 +67,7 @@ namespace vcpkg
bool operator==(const package_spec& left, const package_spec& right)
{
- return left.name == right.name && left.target_triplet == right.target_triplet;
+ return left.name() == right.name() && left.target_triplet() == right.target_triplet();
}
std::ostream& operator<<(std::ostream& os, const package_spec& spec)
diff --git a/toolsrc/src/package_spec_parse_result.cpp b/toolsrc/src/package_spec_parse_result.cpp
index 757b6df53..dc377f656 100644
--- a/toolsrc/src/package_spec_parse_result.cpp
+++ b/toolsrc/src/package_spec_parse_result.cpp
@@ -13,10 +13,12 @@ namespace vcpkg
{
switch (static_cast<package_spec_parse_result>(ev))
{
- case package_spec_parse_result::success:
+ case package_spec_parse_result::SUCCESS:
return "OK";
- case package_spec_parse_result::too_many_colons:
+ case package_spec_parse_result::TOO_MANY_COLONS:
return "Too many colons";
+ case package_spec_parse_result::INVALID_CHARACTERS:
+ return "Contains invalid characters. Only alphanumeric lowercase ASCII characters and dashes are allowed";
default:
Checks::unreachable();
}
diff --git a/toolsrc/src/post_build_lint.cpp b/toolsrc/src/post_build_lint.cpp
index 1d4ca0f67..2b2812d73 100644
--- a/toolsrc/src/post_build_lint.cpp
+++ b/toolsrc/src/post_build_lint.cpp
@@ -71,12 +71,10 @@ namespace vcpkg
System::println(System::color::warning, "Include files should not be duplicated into the /debug/include directory. If this cannot be disabled in the project cmake, use\n"
" file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include)"
);
- return
- lint_status::ERROR;
+ return lint_status::ERROR;
}
- return
- lint_status::SUCCESS;
+ return lint_status::SUCCESS;
}
static lint_status check_for_files_in_debug_share_directory(const package_spec& spec, const vcpkg_paths& paths)
@@ -115,7 +113,7 @@ namespace vcpkg
if (!misplaced_cmake_files.empty())
{
- System::println(System::color::warning, "The following cmake files were found outside /share/%s. Please place cmake files in /share/%s.", spec.name, spec.name);
+ System::println(System::color::warning, "The following cmake files were found outside /share/%s. Please place cmake files in /share/%s.", spec.name(), spec.name());
print_vector_of_files(misplaced_cmake_files);
return lint_status::ERROR;
}
@@ -153,12 +151,12 @@ namespace vcpkg
static lint_status check_for_copyright_file(const package_spec& spec, const vcpkg_paths& paths)
{
- const fs::path copyright_file = paths.packages / spec.dir() / "share" / spec.name / "copyright";
+ const fs::path copyright_file = paths.packages / spec.dir() / "share" / spec.name() / "copyright";
if (fs::exists(copyright_file))
{
return lint_status::SUCCESS;
}
- const fs::path current_buildtrees_dir = paths.buildtrees / spec.name;
+ const fs::path current_buildtrees_dir = paths.buildtrees / spec.name();
const fs::path current_buildtrees_dir_src = current_buildtrees_dir / "src";
std::vector<fs::path> potential_copyright_files;
@@ -177,14 +175,14 @@ namespace vcpkg
}
}
- System::println(System::color::warning, "The software license must be available at ${CURRENT_PACKAGES_DIR}/share/%s/copyright .", spec.name);
+ System::println(System::color::warning, "The software license must be available at ${CURRENT_PACKAGES_DIR}/share/%s/copyright .", spec.name());
if (potential_copyright_files.size() == 1) // if there is only one candidate, provide the cmake lines needed to place it in the proper location
{
const fs::path found_file = potential_copyright_files[0];
const fs::path relative_path = found_file.string().erase(0, current_buildtrees_dir.string().size() + 1); // The +1 is needed to remove the "/"
System::println("\n file(COPY ${CURRENT_BUILDTREES_DIR}/%s DESTINATION ${CURRENT_PACKAGES_DIR}/share/%s)\n"
" file(RENAME ${CURRENT_PACKAGES_DIR}/share/%s/%s ${CURRENT_PACKAGES_DIR}/share/%s/copyright)",
- relative_path.generic_string(), spec.name, spec.name, found_file.filename().generic_string(), spec.name);
+ relative_path.generic_string(), spec.name(), spec.name(), found_file.filename().generic_string(), spec.name());
return lint_status::ERROR;
}
@@ -195,7 +193,7 @@ namespace vcpkg
}
const fs::path current_packages_dir = paths.packages / spec.dir();
- System::println(" %s/share/%s/copyright", current_packages_dir.generic_string(), spec.name);
+ System::println(" %s/share/%s/copyright", current_packages_dir.generic_string(), spec.name());
return lint_status::ERROR;
}
@@ -221,7 +219,7 @@ namespace vcpkg
std::vector<fs::path> dlls_with_no_exports;
for (const fs::path& dll : dlls)
{
- const std::wstring cmd_line = Strings::format(LR"("%s" /exports "%s")", DUMPBIN_EXE.native(), dll.native());
+ const std::wstring cmd_line = Strings::wformat(LR"("%s" /exports "%s")", DUMPBIN_EXE.native(), dll.native());
System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(cmd_line);
Checks::check_exit(ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::utf16_to_utf8(cmd_line));
@@ -252,7 +250,7 @@ namespace vcpkg
std::vector<fs::path> dlls_with_improper_uwp_bit;
for (const fs::path& dll : dlls)
{
- const std::wstring cmd_line = Strings::format(LR"("%s" /headers "%s")", DUMPBIN_EXE.native(), dll.native());
+ const std::wstring cmd_line = Strings::wformat(LR"("%s" /headers "%s")", DUMPBIN_EXE.native(), dll.native());
System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(cmd_line);
Checks::check_exit(ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::utf16_to_utf8(cmd_line));
@@ -284,11 +282,11 @@ namespace vcpkg
std::vector<file_and_arch> binaries_with_invalid_architecture;
for (const fs::path& f : files)
{
- const std::wstring cmd_line = Strings::format(LR"("%s" /headers "%s" | findstr machine)", DUMPBIN_EXE.native(), f.native());
+ const std::wstring cmd_line = Strings::wformat(LR"("%s" /headers "%s" | findstr machine)", DUMPBIN_EXE.native(), f.native());
System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(cmd_line);
Checks::check_exit(ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::utf16_to_utf8(cmd_line));
- if (Strings::case_insensitive_find(ec_data.output, expected_architecture) == ec_data.output.end())
+ if (Strings::case_insensitive_ascii_find(ec_data.output, expected_architecture) == ec_data.output.end())
{
binaries_with_invalid_architecture.push_back({f, ec_data.output});
}
@@ -311,15 +309,27 @@ namespace vcpkg
return lint_status::SUCCESS;
}
- static void operator +=(unsigned int& left, const lint_status& right)
+ static lint_status check_no_dlls_present(const std::vector<fs::path>& dlls)
+ {
+ if (dlls.empty())
+ {
+ return lint_status::SUCCESS;
+ }
+
+ System::println(System::color::warning, "DLLs should not be present in a static build, but the following DLLs were found:");
+ print_vector_of_files(dlls);
+ return lint_status::ERROR;
+ }
+
+ static void operator +=(size_t& left, const lint_status& right)
{
- left += static_cast<unsigned int>(right);
+ left += static_cast<size_t>(right);
}
void perform_all_checks(const package_spec& spec, const vcpkg_paths& paths)
{
System::println("-- Performing post-build validation");
- unsigned int error_count = 0;
+ size_t error_count = 0;
error_count += check_for_files_in_include_directory(spec, paths);
error_count += check_for_files_in_debug_include_directory(spec, paths);
error_count += check_for_files_in_debug_share_directory(spec, paths);
@@ -330,24 +340,42 @@ namespace vcpkg
error_count += check_for_copyright_file(spec, paths);
error_count += check_for_exes(spec, paths);
- std::vector<fs::path> dlls;
- recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "bin", ".dll", dlls);
- recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "debug" / "bin", ".dll", dlls);
-
- error_count += check_exports_of_dlls(dlls);
- error_count += check_uwp_bit_of_dlls(spec.target_triplet.system(), dlls);
- error_count += check_architecture(spec.target_triplet.architecture(), dlls);
+ triplet::BuildType build_type = spec.target_triplet().build_type();
+ switch (build_type)
+ {
+ case triplet::BuildType::DYNAMIC:
+ {
+ std::vector<fs::path> dlls;
+ recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "bin", ".dll", dlls);
+ recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "debug" / "bin", ".dll", dlls);
+
+ error_count += check_exports_of_dlls(dlls);
+ error_count += check_uwp_bit_of_dlls(spec.target_triplet().system(), dlls);
+ error_count += check_architecture(spec.target_triplet().architecture(), dlls);
+ break;
+ }
+ case triplet::BuildType::STATIC:
+ {
+ std::vector<fs::path> dlls;
+ recursive_find_files_with_extension_in_dir(paths.packages / spec.dir(), ".dll", dlls);
+ error_count += check_no_dlls_present(dlls);
+ break;
+ }
+
+ default:
+ Checks::unreachable();
+ }
std::vector<fs::path> libs;
recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "lib", ".lib", libs);
recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "debug" / "lib", ".lib", libs);
- error_count += check_architecture(spec.target_triplet.architecture(), libs);
+ error_count += check_architecture(spec.target_triplet().architecture(), libs);
if (error_count != 0)
{
- const fs::path portfile = paths.ports / spec.name / "portfile.cmake";
- System::println(System::color::error, "Found %d error(s). Please correct the portfile:\n %s", error_count, portfile.string());
+ const fs::path portfile = paths.ports / spec.name() / "portfile.cmake";
+ System::println(System::color::error, "Found %u error(s). Please correct the portfile:\n %s", error_count, portfile.string());
exit(EXIT_FAILURE);
}
diff --git a/toolsrc/src/test.cpp b/toolsrc/src/test.cpp
index 82113abaa..fc49b362d 100644
--- a/toolsrc/src/test.cpp
+++ b/toolsrc/src/test.cpp
@@ -87,11 +87,11 @@ namespace UnitTest1
{"Multi-Arch", "same"},
});
- Assert::AreEqual("zlib", pgh.name.c_str());
+ Assert::AreEqual("zlib", pgh.spec.name().c_str());
Assert::AreEqual("1.2.8", pgh.version.c_str());
Assert::AreEqual("", pgh.maintainer.c_str());
Assert::AreEqual("", pgh.description.c_str());
- Assert::AreEqual("a", pgh.target_triplet.value.c_str());
+ Assert::AreEqual("a", pgh.spec.target_triplet().canonical_name().c_str());
Assert::AreEqual(size_t(0), pgh.depends.size());
}
@@ -106,7 +106,7 @@ namespace UnitTest1
{"Description", "d"},
{"Depends", "bd"}
});
- Assert::AreEqual("s", pgh.name.c_str());
+ Assert::AreEqual("s", pgh.spec.name().c_str());
Assert::AreEqual("v", pgh.version.c_str());
Assert::AreEqual("m", pgh.maintainer.c_str());
Assert::AreEqual("d", pgh.description.c_str());
@@ -308,24 +308,24 @@ namespace UnitTest1
TEST_METHOD(package_spec_parse)
{
- vcpkg::expected<vcpkg::package_spec> spec = vcpkg::parse("zlib", vcpkg::triplet::X86_WINDOWS);
- Assert::AreEqual(vcpkg::package_spec_parse_result::success, vcpkg::to_package_spec_parse_result(spec.error_code()));
- Assert::AreEqual("zlib", spec.get()->name.c_str());
- Assert::AreEqual(vcpkg::triplet::X86_WINDOWS.value, spec.get()->target_triplet.value);
+ vcpkg::expected<vcpkg::package_spec> spec = vcpkg::package_spec::from_string("zlib", vcpkg::triplet::X86_WINDOWS);
+ Assert::AreEqual(vcpkg::package_spec_parse_result::SUCCESS, vcpkg::to_package_spec_parse_result(spec.error_code()));
+ Assert::AreEqual("zlib", spec.get()->name().c_str());
+ Assert::AreEqual(vcpkg::triplet::X86_WINDOWS.canonical_name(), spec.get()->target_triplet().canonical_name());
}
TEST_METHOD(package_spec_parse_with_arch)
{
- vcpkg::expected<vcpkg::package_spec> spec = vcpkg::parse("zlib:x64-uwp", vcpkg::triplet::X86_WINDOWS);
- Assert::AreEqual(vcpkg::package_spec_parse_result::success, vcpkg::to_package_spec_parse_result(spec.error_code()));
- Assert::AreEqual("zlib", spec.get()->name.c_str());
- Assert::AreEqual(vcpkg::triplet::X64_UWP.value, spec.get()->target_triplet.value);
+ vcpkg::expected<vcpkg::package_spec> spec = vcpkg::package_spec::from_string("zlib:x64-uwp", vcpkg::triplet::X86_WINDOWS);
+ Assert::AreEqual(vcpkg::package_spec_parse_result::SUCCESS, vcpkg::to_package_spec_parse_result(spec.error_code()));
+ Assert::AreEqual("zlib", spec.get()->name().c_str());
+ Assert::AreEqual(vcpkg::triplet::X64_UWP.canonical_name(), spec.get()->target_triplet().canonical_name());
}
TEST_METHOD(package_spec_parse_with_multiple_colon)
{
- auto ec = vcpkg::parse("zlib:x86-uwp:", vcpkg::triplet::X86_WINDOWS).error_code();
- Assert::AreEqual(vcpkg::package_spec_parse_result::too_many_colons, vcpkg::to_package_spec_parse_result(ec));
+ auto ec = vcpkg::package_spec::from_string("zlib:x86-uwp:", vcpkg::triplet::X86_WINDOWS).error_code();
+ Assert::AreEqual(vcpkg::package_spec_parse_result::TOO_MANY_COLONS, vcpkg::to_package_spec_parse_result(ec));
}
TEST_METHOD(utf8_to_utf16)
diff --git a/toolsrc/src/triplet.cpp b/toolsrc/src/triplet.cpp
index 9ad3d8847..af2ca2a72 100644
--- a/toolsrc/src/triplet.cpp
+++ b/toolsrc/src/triplet.cpp
@@ -1,18 +1,18 @@
#include "triplet.h"
-#include "vcpkg_System.h"
#include "vcpkg_Checks.h"
+#include <algorithm>
namespace vcpkg
{
- const triplet triplet::X86_WINDOWS = {"x86-windows"};
- const triplet triplet::X64_WINDOWS = {"x64-windows"};
- const triplet triplet::X86_UWP = {"x86-uwp"};
- const triplet triplet::X64_UWP = {"x64-uwp"};
- const triplet triplet::ARM_UWP = {"arm-uwp"};
+ const triplet triplet::X86_WINDOWS = from_canonical_name("x86-windows");
+ const triplet triplet::X64_WINDOWS = from_canonical_name("x64-windows");
+ const triplet triplet::X86_UWP = from_canonical_name("x86-uwp");
+ const triplet triplet::X64_UWP = from_canonical_name("x64-uwp");
+ const triplet triplet::ARM_UWP = from_canonical_name("arm-uwp");
std::string to_string(const triplet& t)
{
- return t.value;
+ return t.canonical_name();
}
std::string to_printf_arg(const triplet& t)
@@ -22,7 +22,7 @@ namespace vcpkg
bool operator==(const triplet& left, const triplet& right)
{
- return left.value == right.value;
+ return left.canonical_name() == right.canonical_name();
}
bool operator!=(const triplet& left, const triplet& right)
@@ -35,25 +35,43 @@ namespace vcpkg
return os << to_string(t);
}
- std::string triplet::architecture() const
+ triplet triplet::from_canonical_name(const std::string& triplet_as_string)
+ {
+ std::string s(triplet_as_string);
+ std::transform(s.begin(), s.end(), s.begin(), ::tolower);
+
+ auto it = std::find(s.cbegin(), s.cend(), '-');
+ Checks::check_exit(it != s.cend(), "Invalid triplet: %s", triplet_as_string);
+
+ triplet t;
+ t.m_canonical_name = s;
+ return t;
+ }
+
+ const std::string& triplet::canonical_name() const
{
- if (*this == X86_WINDOWS || *this == X86_UWP)
- return "x86";
- if (*this == X64_WINDOWS || *this == X64_UWP)
- return "x64";
- if (*this == ARM_UWP)
- return "arm";
+ return this->m_canonical_name;
+ }
- Checks::exit_with_message("Unknown architecture: %s", value);
+ std::string triplet::architecture() const
+ {
+ auto it = std::find(this->m_canonical_name.cbegin(), this->m_canonical_name.cend(), '-');
+ return std::string(this->m_canonical_name.cbegin(), it);
}
std::string triplet::system() const
{
- if (*this == X86_WINDOWS || *this == X64_WINDOWS)
- return "windows";
- if (*this == X86_UWP || *this == X64_UWP || *this == ARM_UWP)
- return "uwp";
+ auto it = std::find(this->m_canonical_name.cbegin(), this->m_canonical_name.cend(), '-');
+ return std::string(it + 1, this->m_canonical_name.cend());
+ }
+
+ triplet::BuildType triplet::build_type() const
+ {
+ if (this->m_canonical_name.find("static") != std::string::npos)
+ {
+ return BuildType::STATIC;
+ }
- Checks::exit_with_message("Unknown system: %s", value);
+ return BuildType::DYNAMIC;
}
}
diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp
index d5433b1f5..db6c03480 100644
--- a/toolsrc/src/vcpkg_Checks.cpp
+++ b/toolsrc/src/vcpkg_Checks.cpp
@@ -34,8 +34,7 @@ namespace vcpkg {namespace Checks
{
if (!expression)
{
- System::println(System::color::error, errorMessage);
- exit(EXIT_FAILURE);
+ exit_with_message(errorMessage);
}
}
}}
diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp
new file mode 100644
index 000000000..54b37cd11
--- /dev/null
+++ b/toolsrc/src/vcpkg_Dependencies.cpp
@@ -0,0 +1,67 @@
+#include "vcpkg_Dependencies.h"
+#include <vector>
+#include "vcpkg_Graphs.h"
+#include "vcpkg_paths.h"
+#include "package_spec.h"
+#include "StatusParagraphs.h"
+#include <unordered_set>
+#include "vcpkg.h"
+#include "vcpkg_Maps.h"
+#include "vcpkg_Sets.h"
+
+namespace vcpkg { namespace Dependencies
+{
+ static Graphs::Graph<package_spec> build_dependency_graph(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db)
+ {
+ std::vector<package_spec> examine_stack(specs);
+ std::unordered_set<package_spec> was_examined; // Examine = we have checked its immediate (non-recursive) dependencies
+ Graphs::Graph<package_spec> graph;
+ graph.add_vertices(examine_stack);
+
+ while (!examine_stack.empty())
+ {
+ const package_spec spec = examine_stack.back();
+ examine_stack.pop_back();
+
+ if (was_examined.find(spec) != was_examined.end())
+ {
+ continue;
+ }
+
+ std::vector<std::string> dependencies_as_string = get_unmet_package_dependencies(paths, spec, status_db);
+
+ for (const std::string& dep_as_string : dependencies_as_string)
+ {
+ const package_spec current_dep = package_spec::from_name_and_triplet(dep_as_string, spec.target_triplet()).get_or_throw();
+ auto it = status_db.find(current_dep.name(), current_dep.target_triplet());
+ if (it != status_db.end() && (*it)->want == want_t::install)
+ {
+ continue;
+ }
+
+ graph.add_edge(spec, current_dep);
+ if (was_examined.find(current_dep) == was_examined.end())
+ {
+ examine_stack.push_back(std::move(current_dep));
+ }
+ }
+
+ was_examined.insert(spec);
+ }
+
+ return graph;
+ }
+
+ std::vector<package_spec> create_dependency_ordered_install_plan(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db)
+ {
+ return build_dependency_graph(paths, specs, status_db).find_topological_sort();
+ }
+
+ std::unordered_set<package_spec> find_unmet_dependencies(const vcpkg_paths& paths, const package_spec& spec, const StatusParagraphs& status_db)
+ {
+ const Graphs::Graph<package_spec> dependency_graph = build_dependency_graph(paths, {spec}, status_db);
+ std::unordered_set<package_spec> key_set = Maps::extract_key_set(dependency_graph.adjacency_list());
+ key_set.erase(spec);
+ return key_set;
+ }
+}}
diff --git a/toolsrc/src/vcpkg_Environment.cpp b/toolsrc/src/vcpkg_Environment.cpp
index f70f2b893..d98b0f220 100644
--- a/toolsrc/src/vcpkg_Environment.cpp
+++ b/toolsrc/src/vcpkg_Environment.cpp
@@ -48,11 +48,11 @@ namespace vcpkg {namespace Environment
void ensure_git_on_path(const vcpkg_paths& paths)
{
const fs::path downloaded_git = paths.downloads / "PortableGit" / "cmd";
- const std::wstring path_buf = Strings::format(L"%s;%s;%s;%s",
- downloaded_git.native(),
- System::wdupenv_str(L"PATH"),
- default_git_installation_dir.native(),
- default_git_installation_dir_x86.native());
+ const std::wstring path_buf = Strings::wformat(L"%s;%s;%s;%s",
+ downloaded_git.native(),
+ System::wdupenv_str(L"PATH"),
+ default_git_installation_dir.native(),
+ default_git_installation_dir_x86.native());
_wputenv_s(L"PATH", path_buf.c_str());
static constexpr std::array<int, 3> git_version = {2,0,0};
@@ -63,11 +63,11 @@ namespace vcpkg {namespace Environment
void ensure_cmake_on_path(const vcpkg_paths& paths)
{
const fs::path downloaded_cmake = paths.downloads / "cmake-3.5.2-win32-x86" / "bin";
- const std::wstring path_buf = Strings::format(L"%s;%s;%s;%s",
- downloaded_cmake.native(),
- System::wdupenv_str(L"PATH"),
- default_cmake_installation_dir.native(),
- default_cmake_installation_dir_x86.native());
+ const std::wstring path_buf = Strings::wformat(L"%s;%s;%s;%s",
+ downloaded_cmake.native(),
+ System::wdupenv_str(L"PATH"),
+ default_cmake_installation_dir.native(),
+ default_cmake_installation_dir_x86.native());
_wputenv_s(L"PATH", path_buf.c_str());
static constexpr std::array<int, 3> cmake_version = {3,5,0};
@@ -77,7 +77,7 @@ namespace vcpkg {namespace Environment
void ensure_nuget_on_path(const vcpkg_paths& paths)
{
- const std::wstring path_buf = Strings::format(L"%s;%s", paths.downloads.native(), System::wdupenv_str(L"PATH"));
+ const std::wstring path_buf = Strings::wformat(L"%s;%s", paths.downloads.native(), System::wdupenv_str(L"PATH"));
_wputenv_s(L"PATH", path_buf.c_str());
static constexpr std::array<int, 3> nuget_version = {1,0,0};
diff --git a/toolsrc/src/vcpkg_Files.cpp b/toolsrc/src/vcpkg_Files.cpp
index 49a661157..611aa7450 100644
--- a/toolsrc/src/vcpkg_Files.cpp
+++ b/toolsrc/src/vcpkg_Files.cpp
@@ -1,16 +1,24 @@
#include "vcpkg_Files.h"
#include <fstream>
#include <filesystem>
+#include <regex>
namespace fs = std::tr2::sys;
namespace vcpkg {namespace Files
{
+ static const std::regex FILESYSTEM_INVALID_CHARACTERS_REGEX = std::regex(R"([\/:*?"<>|])");
+
void check_is_directory(const fs::path& dirpath)
{
Checks::check_throw(fs::is_directory(dirpath), "The path %s is not a directory", dirpath.string());
}
+ bool has_invalid_chars_for_filesystem(const std::string s)
+ {
+ return std::regex_search(s, FILESYSTEM_INVALID_CHARACTERS_REGEX);
+ }
+
expected<std::string> get_contents(const fs::path& file_path) noexcept
{
std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary);
@@ -35,4 +43,19 @@ namespace vcpkg {namespace Files
return std::move(output);
}
+
+ fs::path find_file_recursively_up(const fs::path& starting_dir, const std::string& filename)
+ {
+ fs::path current_dir = starting_dir;
+ for (; !current_dir.empty(); current_dir = current_dir.parent_path())
+ {
+ const fs::path candidate = current_dir / filename;
+ if (fs::exists(candidate))
+ {
+ break;
+ }
+ }
+
+ return current_dir;
+ }
}}
diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp
new file mode 100644
index 000000000..f7aae1929
--- /dev/null
+++ b/toolsrc/src/vcpkg_Input.cpp
@@ -0,0 +1,52 @@
+#include "vcpkg_Input.h"
+#include "vcpkg_System.h"
+#include "metrics.h"
+#include "vcpkg_Commands.h"
+
+namespace vcpkg {namespace Input
+{
+ package_spec check_and_get_package_spec(const std::string& package_spec_as_string, const triplet& default_target_triplet, const char* example_text)
+ {
+ const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string);
+ expected<package_spec> expected_spec = package_spec::from_string(as_lowercase, default_target_triplet);
+ if (auto spec = expected_spec.get())
+ {
+ return *spec;
+ }
+
+ // Intentionally show the lowercased string
+ System::println(System::color::error, "Error: %s: %s", expected_spec.error_code().message(), as_lowercase);
+ System::print(example_text);
+ exit(EXIT_FAILURE);
+ }
+
+ std::vector<package_spec> check_and_get_package_specs(const std::vector<std::string>& package_specs_as_strings, const triplet& default_target_triplet, const char* example_text)
+ {
+ std::vector<package_spec> specs;
+ for (const std::string& spec : package_specs_as_strings)
+ {
+ specs.push_back(check_and_get_package_spec(spec, default_target_triplet, example_text));
+ }
+
+ return specs;
+ }
+
+ void check_triplet(const triplet& t, const vcpkg_paths& paths)
+ {
+ if (!paths.is_valid_triplet(t))
+ {
+ System::println(System::color::error, "Error: invalid triplet: %s", t.canonical_name());
+ TrackProperty("error", "invalid triplet: " + t.canonical_name());
+ help_topic_valid_triplet(paths);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ void check_triplets(std::vector<package_spec> triplets, const vcpkg_paths& paths)
+ {
+ for (const package_spec& spec : triplets)
+ {
+ check_triplet(spec.target_triplet(), paths);
+ }
+ }
+}}
diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp
index b0312536a..56eeae7a0 100644
--- a/toolsrc/src/vcpkg_Strings.cpp
+++ b/toolsrc/src/vcpkg_Strings.cpp
@@ -20,7 +20,7 @@ namespace vcpkg {namespace Strings {namespace details
return output;
}
- std::wstring format_internal(const wchar_t* fmtstr, ...)
+ std::wstring wformat_internal(const wchar_t* fmtstr, ...)
{
va_list lst;
va_start(lst, fmtstr);
@@ -48,13 +48,20 @@ namespace vcpkg {namespace Strings
return conversion.to_bytes(w);
}
- std::string::const_iterator case_insensitive_find(const std::string& s, const std::string& pattern)
+ std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern)
{
- std::string patter_as_lower_case;
- std::transform(pattern.begin(), pattern.end(), back_inserter(patter_as_lower_case), tolower);
- return search(s.begin(), s.end(), patter_as_lower_case.begin(), patter_as_lower_case.end(), [](const char a, const char b)
+ std::string pattern_as_lower_case;
+ std::transform(pattern.begin(), pattern.end(), back_inserter(pattern_as_lower_case), tolower);
+ return search(s.begin(), s.end(), pattern_as_lower_case.begin(), pattern_as_lower_case.end(), [](const char a, const char b)
{
- return (tolower(a) == b);
+ return tolower(a) == b;
});
}
+
+ std::string ascii_to_lowercase(const std::string& input)
+ {
+ std::string output = input;
+ std::transform(output.begin(), output.end(), output.begin(), ::tolower);
+ return output;
+ }
}}
diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp
index 71b4087d2..4dc37857d 100644
--- a/toolsrc/src/vcpkg_System.cpp
+++ b/toolsrc/src/vcpkg_System.cpp
@@ -19,14 +19,14 @@ namespace vcpkg {namespace System
int cmd_execute(const wchar_t* cmd_line)
{
// Basically we are wrapping it in quotes
- const std::wstring& actual_cmd_line = Strings::format(LR"###("%s")###", cmd_line);
+ const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line);
int exit_code = _wsystem(actual_cmd_line.c_str());
return exit_code;
}
exit_code_and_output cmd_execute_and_capture_output(const wchar_t* cmd_line)
{
- const std::wstring& actual_cmd_line = Strings::format(LR"###("%s")###", cmd_line);
+ const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line);
std::string output;
char buf[1024];
diff --git a/toolsrc/src/vcpkg_cmd_arguments.cpp b/toolsrc/src/vcpkg_cmd_arguments.cpp
index 4cfc12716..a286ba9b7 100644
--- a/toolsrc/src/vcpkg_cmd_arguments.cpp
+++ b/toolsrc/src/vcpkg_cmd_arguments.cpp
@@ -166,90 +166,51 @@ namespace vcpkg
return output;
}
- void vcpkg_cmd_arguments::check_max_args(size_t arg_count, const char* example_text) const
+ void vcpkg_cmd_arguments::check_max_arg_count(const size_t expected_arg_count) const
{
- if (command_arguments.size() > arg_count)
- {
- System::println(System::color::error, "Error: too many arguments to command %s", command);
- if (example_text != nullptr)
- print_example(example_text);
- else
- print_usage();
- exit(EXIT_FAILURE);
- }
+ return check_max_arg_count(expected_arg_count, "");
}
- std::vector<package_spec> vcpkg_cmd_arguments::extract_package_specs_with_unmet_dependencies(const vcpkg_paths& paths, const triplet& default_target_triplet, const StatusParagraphs& status_db) const
+ void vcpkg_cmd_arguments::check_min_arg_count(const size_t expected_arg_count) const
{
- std::vector<package_spec> specs = parse_all_arguments_as_package_specs(default_target_triplet);
- std::unordered_set<package_spec> had_its_immediate_dependencies_added;
- Graphs::Graph<package_spec> graph;
- graph.add_vertices(specs);
-
- while (!specs.empty())
- {
- package_spec spec = specs.back();
- specs.pop_back();
-
- if (had_its_immediate_dependencies_added.find(spec) != had_its_immediate_dependencies_added.end())
- {
- continue;
- }
-
- std::vector<std::string> dependencies_as_string = get_unmet_package_dependencies(paths, spec, status_db);
-
- for (const std::string& dep_as_string : dependencies_as_string)
- {
- package_spec current_dep = {dep_as_string, spec.target_triplet};
- auto it = status_db.find(current_dep.name, current_dep.target_triplet);
- if (it != status_db.end() && (*it)->want == want_t::install)
- {
- continue;
- }
+ return check_min_arg_count(expected_arg_count, "");
+ }
- graph.add_edge(spec, current_dep);
- if (had_its_immediate_dependencies_added.find(current_dep) == had_its_immediate_dependencies_added.end())
- {
- specs.push_back(std::move(current_dep));
- }
- }
+ void vcpkg_cmd_arguments::check_exact_arg_count(const size_t expected_arg_count) const
+ {
+ return check_exact_arg_count(expected_arg_count, "");
+ }
- had_its_immediate_dependencies_added.insert(spec);
+ void vcpkg_cmd_arguments::check_max_arg_count(const size_t expected_arg_count, const char* example_text) const
+ {
+ const size_t actual_arg_count = command_arguments.size();
+ if (actual_arg_count > expected_arg_count)
+ {
+ System::println(System::color::error, "Error: `%s` requires at most %u arguments, but %u were provided", this->command, expected_arg_count, actual_arg_count);
+ System::print(example_text);
+ exit(EXIT_FAILURE);
}
-
- return graph.find_topological_sort();
}
- std::vector<package_spec> vcpkg_cmd_arguments::parse_all_arguments_as_package_specs(const triplet& default_target_triplet, const char* example_text) const
+ void vcpkg_cmd_arguments::check_min_arg_count(const size_t expected_arg_count, const char* example_text) const
{
- size_t arg_count = command_arguments.size();
- if (arg_count < 1)
+ const size_t actual_arg_count = command_arguments.size();
+ if (actual_arg_count < expected_arg_count)
{
- System::println(System::color::error, "Error: %s requires one or more package specifiers", this->command);
- if (example_text == nullptr)
- print_example(Strings::format("%s zlib zlib:x64-windows curl boost", this->command).c_str());
- else
- print_example(example_text);
+ System::println(System::color::error, "Error: `%s` requires at least %u arguments, but %u were provided", this->command, expected_arg_count, actual_arg_count);
+ System::print(example_text);
exit(EXIT_FAILURE);
}
- std::vector<package_spec> specs;
- specs.reserve(arg_count);
+ }
- for (const std::string& command_argument : command_arguments)
+ void vcpkg_cmd_arguments::check_exact_arg_count(const size_t expected_arg_count, const char* example_text) const
+ {
+ const size_t actual_arg_count = command_arguments.size();
+ if (actual_arg_count != expected_arg_count)
{
- expected<package_spec> current_spec = vcpkg::parse(command_argument, default_target_triplet);
- if (auto spec = current_spec.get())
- {
- specs.push_back(std::move(*spec));
- }
- else
- {
- System::println(System::color::error, "Error: %s: %s", current_spec.error_code().message(), command_argument);
- print_example(Strings::format("%s zlib:x64-windows", this->command).c_str());
- exit(EXIT_FAILURE);
- }
+ System::println(System::color::error, "Error: `%s` requires %u arguments, but %u were provided", this->command, expected_arg_count, actual_arg_count);
+ System::print(example_text);
+ exit(EXIT_FAILURE);
}
-
- return specs;
}
}
diff --git a/toolsrc/src/vcpkg_paths.cpp b/toolsrc/src/vcpkg_paths.cpp
index 10b6d992a..1f9eb0bc5 100644
--- a/toolsrc/src/vcpkg_paths.cpp
+++ b/toolsrc/src/vcpkg_paths.cpp
@@ -3,8 +3,7 @@
#include "vcpkg_paths.h"
#include "metrics.h"
#include "vcpkg_System.h"
-
-namespace fs = std::tr2::sys;
+#include "package_spec.h"
namespace vcpkg
{
@@ -45,4 +44,29 @@ namespace vcpkg
paths.ports_cmake = paths.root / "scripts" / "ports.cmake";
return paths;
}
+
+ fs::path vcpkg_paths::package_dir(const package_spec& spec) const
+ {
+ return this->packages / spec.dir();
+ }
+
+ fs::path vcpkg_paths::port_dir(const package_spec& spec) const
+ {
+ return this->ports / spec.name();
+ }
+
+ bool vcpkg_paths::is_valid_triplet(const triplet& t) const
+ {
+ auto it = fs::directory_iterator(this->triplets);
+ for (; it != fs::directory_iterator(); ++it)
+ {
+ std::string triplet_file_name = it->path().stem().generic_u8string();
+ if (t.canonical_name() == triplet_file_name) // TODO: fuzzy compare
+ {
+ //t.value = triplet_file_name; // NOTE: uncomment when implementing fuzzy compare
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/toolsrc/src/vcpkglib_helpers.cpp b/toolsrc/src/vcpkglib_helpers.cpp
index e947dc647..3aa3735b0 100644
--- a/toolsrc/src/vcpkglib_helpers.cpp
+++ b/toolsrc/src/vcpkglib_helpers.cpp
@@ -4,29 +4,28 @@
namespace vcpkg {namespace details
{
- void optional_field(const std::unordered_map<std::string, std::string>& fields, std::string& out, const std::string& fieldname)
+ std::string optional_field(const std::unordered_map<std::string, std::string>& fields, const std::string& fieldname)
{
auto it = fields.find(fieldname);
if (it == fields.end())
{
- out.clear();
+ return std::string();
}
- else
- {
- out = it->second;
- }
+ return it->second;
};
- void required_field(const std::unordered_map<std::string, std::string>& fields, std::string& out, const std::string& fieldname)
+ std::string required_field(const std::unordered_map<std::string, std::string>& fields, const std::string& fieldname)
{
auto it = fields.find(fieldname);
vcpkg::Checks::check_throw(it != fields.end(), "Required field not present: %s", fieldname);
- out = it->second;
+ return it->second;
};
- void parse_depends(const std::string& depends_string, std::vector<std::string>& out)
+ std::vector<std::string> parse_depends(const std::string& depends_string)
{
+ std::vector<std::string> out;
+
size_t cur = 0;
do
{
@@ -34,17 +33,21 @@ namespace vcpkg {namespace details
if (pos == std::string::npos)
{
out.push_back(depends_string.substr(cur));
- return;
+ break;
}
out.push_back(depends_string.substr(cur, pos - cur));
// skip comma and space
++pos;
if (depends_string[pos] == ' ')
+ {
++pos;
+ }
cur = pos;
}
while (cur != std::string::npos);
+
+ return out;
}
}}