2017-01-28 04:49:09 +08:00
|
|
|
#include "pch.h"
|
2016-09-19 11:50:08 +08:00
|
|
|
#include "expected.h"
|
|
|
|
#include "vcpkg_paths.h"
|
|
|
|
#include "metrics.h"
|
|
|
|
#include "vcpkg_System.h"
|
2016-09-24 05:25:17 +08:00
|
|
|
#include "package_spec.h"
|
2017-03-11 08:30:44 +08:00
|
|
|
#include "vcpkg_Environment.h"
|
2016-09-19 11:50:08 +08:00
|
|
|
|
|
|
|
namespace vcpkg
|
|
|
|
{
|
2017-03-11 08:30:44 +08:00
|
|
|
static bool exists_and_has_equal_or_greater_version(const std::wstring& version_cmd, const std::array<int, 3>& expected_version)
|
|
|
|
{
|
|
|
|
static const std::regex re(R"###((\d+)\.(\d+)\.(\d+))###");
|
|
|
|
|
2017-03-14 07:17:47 +08:00
|
|
|
auto rc = System::cmd_execute_and_capture_output(Strings::wformat(LR"(%s)", version_cmd));
|
2017-03-11 08:30:44 +08:00
|
|
|
if (rc.exit_code != 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::match_results<std::string::const_iterator> match;
|
|
|
|
auto found = std::regex_search(rc.output, match, re);
|
|
|
|
if (!found)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int d1 = atoi(match[1].str().c_str());
|
|
|
|
int d2 = atoi(match[2].str().c_str());
|
|
|
|
int d3 = atoi(match[3].str().c_str());
|
|
|
|
if (d1 > expected_version[0] || (d1 == expected_version[0] && d2 > expected_version[1]) || (d1 == expected_version[0] && d2 == expected_version[1] && d3 >= expected_version[2]))
|
|
|
|
{
|
|
|
|
// satisfactory version found
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static optional<fs::path> find_if_has_equal_or_greater_version(const std::vector<fs::path>& candidate_paths, const std::wstring& version_check_arguments, const std::array<int, 3>& expected_version)
|
|
|
|
{
|
|
|
|
auto it = std::find_if(candidate_paths.cbegin(), candidate_paths.cend(), [&](const fs::path& p)
|
2017-03-11 09:01:41 +08:00
|
|
|
{
|
|
|
|
const std::wstring cmd = Strings::wformat(LR"("%s" %s)", p.native(), version_check_arguments);
|
|
|
|
return exists_and_has_equal_or_greater_version(cmd, expected_version);
|
|
|
|
});
|
2017-03-11 08:30:44 +08:00
|
|
|
|
|
|
|
if (it != candidate_paths.cend())
|
|
|
|
{
|
|
|
|
return std::make_unique<fs::path>(std::move(*it));
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::vector<fs::path> find_from_PATH(const std::wstring& name)
|
|
|
|
{
|
2017-03-14 07:17:47 +08:00
|
|
|
const std::wstring cmd = Strings::wformat(L"where.exe %s", name);
|
2017-03-11 08:30:44 +08:00
|
|
|
auto out = System::cmd_execute_and_capture_output(cmd);
|
|
|
|
if (out.exit_code != 0)
|
|
|
|
{
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::vector<std::string> paths_to_add = Strings::split(out.output, "\n");
|
|
|
|
std::vector<fs::path> v;
|
|
|
|
v.insert(v.end(), paths_to_add.cbegin(), paths_to_add.cend());
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
static fs::path fetch_dependency(const fs::path scripts_folder, const std::wstring& tool_name, const fs::path& expected_downloaded_path)
|
|
|
|
{
|
|
|
|
const fs::path script = scripts_folder / "fetchDependency.ps1";
|
|
|
|
auto install_cmd = System::create_powershell_script_cmd(script, Strings::wformat(L"-Dependency %s", tool_name));
|
|
|
|
System::exit_code_and_output rc = System::cmd_execute_and_capture_output(install_cmd);
|
|
|
|
if (rc.exit_code)
|
|
|
|
{
|
|
|
|
System::println(System::color::error, "Launching powershell failed or was denied");
|
|
|
|
TrackProperty("error", "powershell install failed");
|
|
|
|
TrackProperty("installcmd", install_cmd);
|
|
|
|
exit(rc.exit_code);
|
|
|
|
}
|
|
|
|
|
|
|
|
const fs::path actual_downloaded_path = rc.output;
|
2017-03-14 08:38:04 +08:00
|
|
|
Checks::check_exit(VCPKG_LINE_INFO, expected_downloaded_path == actual_downloaded_path, "Expected dependency downloaded path to be %s, but was %s",
|
|
|
|
expected_downloaded_path.generic_string(), actual_downloaded_path.generic_string());
|
2017-03-11 08:30:44 +08:00
|
|
|
return actual_downloaded_path;
|
|
|
|
}
|
|
|
|
|
|
|
|
static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path scripts_folder)
|
|
|
|
{
|
|
|
|
static constexpr std::array<int, 3> expected_version = { 3,8,0 };
|
|
|
|
static const std::wstring version_check_arguments = L"--version";
|
|
|
|
|
|
|
|
const fs::path downloaded_copy = downloads_folder / "cmake-3.8.0-rc1-win32-x86" / "bin" / "cmake.exe";
|
|
|
|
const std::vector<fs::path> from_path = find_from_PATH(L"cmake");
|
|
|
|
|
|
|
|
std::vector<fs::path> candidate_paths;
|
|
|
|
candidate_paths.push_back(downloaded_copy);
|
|
|
|
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
|
|
|
|
candidate_paths.push_back(Environment::get_ProgramFiles_platform_bitness() / "CMake" / "bin" / "cmake.exe");
|
|
|
|
candidate_paths.push_back(Environment::get_ProgramFiles_32_bit() / "CMake" / "bin");
|
|
|
|
|
|
|
|
if (auto ret = find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version))
|
|
|
|
{
|
|
|
|
return *ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fetch_dependency(scripts_folder, L"cmake", downloaded_copy);
|
|
|
|
}
|
|
|
|
|
|
|
|
fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path scripts_folder)
|
|
|
|
{
|
|
|
|
static constexpr std::array<int, 3> expected_version = { 3,3,0 };
|
|
|
|
static const std::wstring version_check_arguments = L"";
|
|
|
|
|
|
|
|
const fs::path downloaded_copy = downloads_folder / "nuget-3.5.0" / "nuget.exe";
|
|
|
|
const std::vector<fs::path> from_path = find_from_PATH(L"nuget");
|
|
|
|
|
|
|
|
std::vector<fs::path> candidate_paths;
|
|
|
|
candidate_paths.push_back(downloaded_copy);
|
|
|
|
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
|
|
|
|
|
|
|
|
if (auto ret = find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version))
|
|
|
|
{
|
|
|
|
return *ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fetch_dependency(scripts_folder, L"nuget", downloaded_copy);
|
|
|
|
}
|
|
|
|
|
|
|
|
fs::path get_git_path(const fs::path& downloads_folder, const fs::path scripts_folder)
|
|
|
|
{
|
|
|
|
static constexpr std::array<int, 3> expected_version = { 2,0,0 };
|
|
|
|
static const std::wstring version_check_arguments = L"--version";
|
|
|
|
|
|
|
|
const fs::path downloaded_copy = downloads_folder / "MinGit-2.11.1-32-bit" / "cmd" / "git.exe";
|
|
|
|
const std::vector<fs::path> from_path = find_from_PATH(L"git");
|
|
|
|
|
|
|
|
std::vector<fs::path> candidate_paths;
|
|
|
|
candidate_paths.push_back(downloaded_copy);
|
|
|
|
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
|
|
|
|
candidate_paths.push_back(Environment::get_ProgramFiles_platform_bitness() / "git" / "cmd" / "git.exe");
|
|
|
|
candidate_paths.push_back(Environment::get_ProgramFiles_32_bit() / "git" / "cmd" / "git.exe");
|
|
|
|
|
|
|
|
if (auto ret = find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version))
|
|
|
|
{
|
|
|
|
return *ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fetch_dependency(scripts_folder, L"git", downloaded_copy);
|
|
|
|
}
|
|
|
|
|
2016-09-19 11:50:08 +08:00
|
|
|
expected<vcpkg_paths> vcpkg_paths::create(const fs::path& vcpkg_root_dir)
|
|
|
|
{
|
|
|
|
std::error_code ec;
|
|
|
|
const fs::path canonical_vcpkg_root_dir = fs::canonical(vcpkg_root_dir, ec);
|
|
|
|
if (ec)
|
|
|
|
{
|
|
|
|
return ec;
|
|
|
|
}
|
|
|
|
|
|
|
|
vcpkg_paths paths;
|
|
|
|
paths.root = canonical_vcpkg_root_dir;
|
|
|
|
|
|
|
|
if (paths.root.empty())
|
|
|
|
{
|
|
|
|
System::println(System::color::error, "Invalid vcpkg root directory: %s", paths.root.string());
|
|
|
|
TrackProperty("error", "Invalid vcpkg root directory");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
paths.packages = paths.root / "packages";
|
|
|
|
paths.buildtrees = paths.root / "buildtrees";
|
|
|
|
paths.downloads = paths.root / "downloads";
|
|
|
|
paths.ports = paths.root / "ports";
|
|
|
|
paths.installed = paths.root / "installed";
|
|
|
|
paths.triplets = paths.root / "triplets";
|
2017-01-24 07:12:43 +08:00
|
|
|
paths.scripts = paths.root / "scripts";
|
2016-09-19 11:50:08 +08:00
|
|
|
|
2017-01-24 07:12:43 +08:00
|
|
|
paths.buildsystems = paths.scripts / "buildsystems";
|
2016-09-19 11:50:08 +08:00
|
|
|
paths.buildsystems_msbuild_targets = paths.buildsystems / "msbuild" / "vcpkg.targets";
|
|
|
|
|
|
|
|
paths.vcpkg_dir = paths.installed / "vcpkg";
|
|
|
|
paths.vcpkg_dir_status_file = paths.vcpkg_dir / "status";
|
|
|
|
paths.vcpkg_dir_info = paths.vcpkg_dir / "info";
|
|
|
|
paths.vcpkg_dir_updates = paths.vcpkg_dir / "updates";
|
|
|
|
|
2017-01-24 07:12:43 +08:00
|
|
|
paths.ports_cmake = paths.scripts / "ports.cmake";
|
2017-03-11 08:30:44 +08:00
|
|
|
|
2016-09-19 11:50:08 +08:00
|
|
|
return paths;
|
|
|
|
}
|
2016-09-24 05:25:17 +08:00
|
|
|
|
2016-09-24 05:32:56 +08:00
|
|
|
fs::path vcpkg_paths::package_dir(const package_spec& spec) const
|
2016-09-24 05:25:17 +08:00
|
|
|
{
|
2016-09-24 05:32:56 +08:00
|
|
|
return this->packages / spec.dir();
|
2016-09-24 05:25:17 +08:00
|
|
|
}
|
|
|
|
|
2016-09-24 05:32:56 +08:00
|
|
|
fs::path vcpkg_paths::port_dir(const package_spec& spec) const
|
2016-09-24 05:25:17 +08:00
|
|
|
{
|
2016-10-04 08:45:01 +08:00
|
|
|
return this->ports / spec.name();
|
2016-09-24 05:25:17 +08:00
|
|
|
}
|
2016-09-29 03:39:05 +08:00
|
|
|
|
2016-11-09 06:12:49 +08:00
|
|
|
fs::path vcpkg_paths::build_info_file_path(const package_spec& spec) const
|
|
|
|
{
|
|
|
|
return this->package_dir(spec) / "BUILD_INFO";
|
|
|
|
}
|
|
|
|
|
2016-11-08 09:54:23 +08:00
|
|
|
fs::path vcpkg_paths::listfile_path(const BinaryParagraph& pgh) const
|
|
|
|
{
|
|
|
|
return this->vcpkg_dir_info / (pgh.fullstem() + ".list");
|
|
|
|
}
|
|
|
|
|
2016-09-30 03:35:27 +08:00
|
|
|
bool vcpkg_paths::is_valid_triplet(const triplet& t) const
|
2016-09-29 03:39:05 +08:00
|
|
|
{
|
|
|
|
auto it = fs::directory_iterator(this->triplets);
|
|
|
|
for (; it != fs::directory_iterator(); ++it)
|
|
|
|
{
|
|
|
|
std::string triplet_file_name = it->path().stem().generic_u8string();
|
2016-10-04 08:20:52 +08:00
|
|
|
if (t.canonical_name() == triplet_file_name) // TODO: fuzzy compare
|
2016-09-29 03:39:05 +08:00
|
|
|
{
|
|
|
|
//t.value = triplet_file_name; // NOTE: uncomment when implementing fuzzy compare
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2017-03-11 08:30:44 +08:00
|
|
|
|
|
|
|
const fs::path& vcpkg_paths::get_cmake_exe() const
|
|
|
|
{
|
|
|
|
return this->cmake_exe.get_lazy([this]() { return get_cmake_path(this->downloads, this->scripts); });
|
|
|
|
}
|
|
|
|
|
|
|
|
const fs::path& vcpkg_paths::get_git_exe() const
|
|
|
|
{
|
|
|
|
return this->git_exe.get_lazy([this]() { return get_git_path(this->downloads, this->scripts); });
|
|
|
|
}
|
|
|
|
|
|
|
|
const fs::path& vcpkg_paths::get_nuget_exe() const
|
|
|
|
{
|
|
|
|
return this->nuget_exe.get_lazy([this]() { return get_nuget_path(this->downloads, this->scripts); });
|
|
|
|
}
|
2016-09-19 11:50:08 +08:00
|
|
|
}
|