[vcpkg] Add x-set-installed command (#10817)

This command takes a list of ports, and causes the final state of the
installed directory to be as-if one ran the install on an empty
installed directory (removing any unnecessary packages).

This is especially useful with the new `--x-install-root` option, which
allows one to set the `installed` directory for vcpkg to use.

Additionally, as a drive-by, we do some `stdfs` clean-up and add a
`.is_feature()` member function to BinaryParagraph (as opposed to
checking for `.feature().empty()`, which is far less clear to read).

This feature is experimental.
This commit is contained in:
nicole mazzuca 2020-04-17 15:49:59 -07:00 committed by GitHub
parent 71377f69e2
commit 556325a1f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 227 additions and 36 deletions

View File

@ -22,6 +22,7 @@ namespace fs
using stdfs::path; using stdfs::path;
using stdfs::perms; using stdfs::perms;
using stdfs::u8path; using stdfs::u8path;
using stdfs::directory_iterator;
#if defined(_WIN32) #if defined(_WIN32)
enum class file_type enum class file_type
@ -155,9 +156,13 @@ namespace vcpkg::Files
fs::file_status status(const fs::path& p, ignore_errors_t) const noexcept; fs::file_status status(const fs::path& p, ignore_errors_t) const noexcept;
fs::file_status symlink_status(LineInfo li, const fs::path& p) const noexcept; fs::file_status symlink_status(LineInfo li, const fs::path& p) const noexcept;
fs::file_status symlink_status(const fs::path& p, ignore_errors_t) const noexcept; fs::file_status symlink_status(const fs::path& p, ignore_errors_t) const noexcept;
virtual fs::path absolute(const fs::path& path, std::error_code& ec) const = 0;
fs::path absolute(LineInfo li, const fs::path& path) const;
virtual fs::path canonical(const fs::path& path, std::error_code& ec) const = 0; virtual fs::path canonical(const fs::path& path, std::error_code& ec) const = 0;
fs::path canonical(LineInfo li, const fs::path& path) const; fs::path canonical(LineInfo li, const fs::path& path) const;
fs::path canonical(const fs::path& path, ignore_errors_t) const; fs::path canonical(const fs::path& path, ignore_errors_t) const;
virtual fs::path current_path(std::error_code&) const = 0;
fs::path current_path(LineInfo li) const;
virtual std::vector<fs::path> find_from_PATH(const std::string& name) const = 0; virtual std::vector<fs::path> find_from_PATH(const std::string& name) const = 0;
}; };

View File

@ -28,6 +28,8 @@ namespace vcpkg
std::string dir() const; std::string dir() const;
bool is_feature() const { return !feature.empty(); }
PackageSpec spec; PackageSpec spec;
std::string version; std::string version;
std::string description; std::string description;

View File

@ -139,6 +139,12 @@ namespace vcpkg::Commands
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths); void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths);
} }
namespace SetInstalled
{
extern const CommandStructure COMMAND_STRUCTURE;
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet);
}
template<class T> template<class T>
struct PackageNameAndFunction struct PackageNameAndFunction
{ {

View File

@ -40,7 +40,7 @@ namespace vcpkg
std::vector<std::unique_ptr<StatusParagraph>*> find_all(const std::string& name, Triplet triplet); std::vector<std::unique_ptr<StatusParagraph>*> find_all(const std::string& name, Triplet triplet);
Optional<InstalledPackageView> find_all_installed(const PackageSpec& spec) const; Optional<InstalledPackageView> get_installed_package_view(const PackageSpec& spec) const;
/// <summary>Find the StatusParagraph for given spec if installed</summary> /// <summary>Find the StatusParagraph for given spec if installed</summary>
/// <param name="spec">Package specification to find the status for</param> /// <param name="spec">Package specification to find the status for</param>

View File

@ -86,6 +86,7 @@ namespace vcpkg
static VcpkgCmdArguments create_from_arg_sequence(const std::string* arg_begin, const std::string* arg_end); static VcpkgCmdArguments create_from_arg_sequence(const std::string* arg_begin, const std::string* arg_end);
std::unique_ptr<std::string> vcpkg_root_dir; std::unique_ptr<std::string> vcpkg_root_dir;
std::unique_ptr<std::string> install_root_dir;
std::unique_ptr<std::string> scripts_root_dir; std::unique_ptr<std::string> scripts_root_dir;
std::unique_ptr<std::string> triplet; std::unique_ptr<std::string> triplet;
std::unique_ptr<std::vector<std::string>> overlay_ports; std::unique_ptr<std::vector<std::string>> overlay_ports;

View File

@ -58,6 +58,7 @@ namespace vcpkg
}; };
static Expected<VcpkgPaths> create(const fs::path& vcpkg_root_dir, static Expected<VcpkgPaths> create(const fs::path& vcpkg_root_dir,
const Optional<fs::path>& install_root_dir,
const Optional<fs::path>& vcpkg_scripts_root_dir, const Optional<fs::path>& vcpkg_scripts_root_dir,
const std::string& default_vs_path, const std::string& default_vs_path,
const std::vector<std::string>* triplets_dirs); const std::vector<std::string>* triplets_dirs);

View File

@ -62,6 +62,8 @@ static void invalid_command(const std::string& cmd)
static void inner(const VcpkgCmdArguments& args) static void inner(const VcpkgCmdArguments& args)
{ {
auto& fs = Files::get_real_filesystem();
Metrics::g_metrics.lock()->track_property("command", args.command); Metrics::g_metrics.lock()->track_property("command", args.command);
if (args.command.empty()) if (args.command.empty())
{ {
@ -88,26 +90,26 @@ static void inner(const VcpkgCmdArguments& args)
} }
fs::path vcpkg_root_dir; fs::path vcpkg_root_dir;
if (args.vcpkg_root_dir != nullptr) if (args.vcpkg_root_dir)
{ {
vcpkg_root_dir = fs::stdfs::absolute(fs::u8path(*args.vcpkg_root_dir)); vcpkg_root_dir = fs.absolute(VCPKG_LINE_INFO, fs::u8path(*args.vcpkg_root_dir));
} }
else else
{ {
const auto vcpkg_root_dir_env = System::get_environment_variable("VCPKG_ROOT"); const auto vcpkg_root_dir_env = System::get_environment_variable("VCPKG_ROOT");
if (const auto v = vcpkg_root_dir_env.get()) if (const auto v = vcpkg_root_dir_env.get())
{ {
vcpkg_root_dir = fs::stdfs::absolute(*v); vcpkg_root_dir = fs.absolute(VCPKG_LINE_INFO, *v);
} }
else else
{ {
const fs::path current_path = fs::stdfs::current_path(); const fs::path current_path = fs.current_path(VCPKG_LINE_INFO);
vcpkg_root_dir = Files::get_real_filesystem().find_file_recursively_up(current_path, ".vcpkg-root"); vcpkg_root_dir = fs.find_file_recursively_up(current_path, ".vcpkg-root");
if (vcpkg_root_dir.empty()) if (vcpkg_root_dir.empty())
{ {
vcpkg_root_dir = Files::get_real_filesystem().find_file_recursively_up( vcpkg_root_dir = fs.find_file_recursively_up(
fs::stdfs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root"); fs.absolute(VCPKG_LINE_INFO, System::get_exe_path_of_current_process()), ".vcpkg-root");
} }
} }
} }
@ -116,17 +118,23 @@ static void inner(const VcpkgCmdArguments& args)
Debug::print("Using vcpkg-root: ", vcpkg_root_dir.u8string(), '\n'); Debug::print("Using vcpkg-root: ", vcpkg_root_dir.u8string(), '\n');
Optional<fs::path> install_root_dir;
if (args.install_root_dir) {
install_root_dir = Files::get_real_filesystem().canonical(VCPKG_LINE_INFO, fs::u8path(*args.install_root_dir));
Debug::print("Using install-root: ", install_root_dir.value_or_exit(VCPKG_LINE_INFO).u8string(), '\n');
}
Optional<fs::path> vcpkg_scripts_root_dir = nullopt; Optional<fs::path> vcpkg_scripts_root_dir = nullopt;
if (nullptr != args.scripts_root_dir) if (args.scripts_root_dir)
{ {
vcpkg_scripts_root_dir = fs::stdfs::canonical(fs::u8path(*args.scripts_root_dir)); vcpkg_scripts_root_dir = Files::get_real_filesystem().canonical(VCPKG_LINE_INFO, fs::u8path(*args.scripts_root_dir));
Debug::print("Using scripts-root: ", vcpkg_scripts_root_dir.value_or_exit(VCPKG_LINE_INFO).u8string(), '\n'); Debug::print("Using scripts-root: ", vcpkg_scripts_root_dir.value_or_exit(VCPKG_LINE_INFO).u8string(), '\n');
} }
auto default_vs_path = System::get_environment_variable("VCPKG_VISUAL_STUDIO_PATH").value_or(""); auto default_vs_path = System::get_environment_variable("VCPKG_VISUAL_STUDIO_PATH").value_or("");
const Expected<VcpkgPaths> expected_paths = const Expected<VcpkgPaths> expected_paths =
VcpkgPaths::create(vcpkg_root_dir, vcpkg_scripts_root_dir, default_vs_path, args.overlay_triplets.get()); VcpkgPaths::create(vcpkg_root_dir, install_root_dir, vcpkg_scripts_root_dir, default_vs_path, args.overlay_triplets.get());
Checks::check_exit(VCPKG_LINE_INFO, Checks::check_exit(VCPKG_LINE_INFO,
!expected_paths.error(), !expected_paths.error(),
"Error: Invalid vcpkg root directory %s: %s", "Error: Invalid vcpkg root directory %s: %s",

View File

@ -272,6 +272,14 @@ namespace vcpkg::Files
this->remove_all(path, ec, failure_point); this->remove_all(path, ec, failure_point);
} }
fs::path Filesystem::absolute(LineInfo li, const fs::path& path) const
{
std::error_code ec;
const auto result = this->absolute(path, ec);
if (ec) Checks::exit_with_message(li, "Error getting absolute path of %s: %s", path.string(), ec.message());
return result;
}
fs::path Filesystem::canonical(LineInfo li, const fs::path& path) const fs::path Filesystem::canonical(LineInfo li, const fs::path& path) const
{ {
std::error_code ec; std::error_code ec;
@ -286,6 +294,14 @@ namespace vcpkg::Files
std::error_code ec; std::error_code ec;
return this->canonical(path, ec); return this->canonical(path, ec);
} }
fs::path Filesystem::current_path(LineInfo li) const
{
std::error_code ec;
const auto result = this->current_path(ec);
if (ec) Checks::exit_with_message(li, "Error getting current path: %s", ec.message());
return result;
}
struct RealFilesystem final : Filesystem struct RealFilesystem final : Filesystem
{ {
@ -699,11 +715,36 @@ namespace vcpkg::Files
} }
} }
virtual fs::path absolute(const fs::path& path, std::error_code& ec) const override
{
#if USE_STD_FILESYSTEM
return fs::stdfs::absolute(path, ec);
#else // ^^^ USE_STD_FILESYSTEM / !USE_STD_FILESYSTEM vvv
#if _WIN32
// absolute was called system_complete in experimental filesystem
return fs::stdfs::system_complete(path, ec);
#else // ^^^ _WIN32 / !_WIN32 vvv
if (path.is_absolute()) {
auto current_path = this->current_path(ec);
if (ec) return fs::path();
return std::move(current_path) / path;
} else {
return path;
}
#endif
#endif
}
virtual fs::path canonical(const fs::path& path, std::error_code& ec) const override virtual fs::path canonical(const fs::path& path, std::error_code& ec) const override
{ {
return fs::stdfs::canonical(path, ec); return fs::stdfs::canonical(path, ec);
} }
virtual fs::path current_path(std::error_code& ec) const override
{
return fs::stdfs::current_path(ec);
}
virtual std::vector<fs::path> find_from_PATH(const std::string& name) const override virtual std::vector<fs::path> find_from_PATH(const std::string& name) const override
{ {
#if defined(_WIN32) #if defined(_WIN32)

View File

@ -171,7 +171,7 @@ namespace
{ {
fs.copy_file(log_file.path(), fs.copy_file(log_file.path(),
tmp_log_path_destination / log_file.path().filename(), tmp_log_path_destination / log_file.path().filename(),
fs::stdfs::copy_options::none, fs::copy_options::none,
ec); ec);
} }
} }

View File

@ -62,7 +62,7 @@ namespace vcpkg
// for compatibility with previous vcpkg versions, we discard all irrelevant information // for compatibility with previous vcpkg versions, we discard all irrelevant information
return dep.name; return dep.name;
}); });
if (this->feature.empty()) if (!this->is_feature())
{ {
this->default_features = parse_default_features_list(parser.optional_field(Fields::DEFAULTFEATURES)) this->default_features = parse_default_features_list(parser.optional_field(Fields::DEFAULTFEATURES))
.value_or_exit(VCPKG_LINE_INFO); .value_or_exit(VCPKG_LINE_INFO);
@ -109,7 +109,7 @@ namespace vcpkg
std::string BinaryParagraph::displayname() const std::string BinaryParagraph::displayname() const
{ {
if (this->feature.empty() || this->feature == "core") if (!this->is_feature() || this->feature == "core")
return Strings::format("%s:%s", this->spec.name(), this->spec.triplet()); return Strings::format("%s:%s", this->spec.name(), this->spec.triplet());
return Strings::format("%s[%s]:%s", this->spec.name(), this->feature, this->spec.triplet()); return Strings::format("%s[%s]:%s", this->spec.name(), this->feature, this->spec.triplet());
} }
@ -126,7 +126,7 @@ namespace vcpkg
out_str.append("Package: ").append(pgh.spec.name()).push_back('\n'); out_str.append("Package: ").append(pgh.spec.name()).push_back('\n');
if (!pgh.version.empty()) if (!pgh.version.empty())
out_str.append("Version: ").append(pgh.version).push_back('\n'); out_str.append("Version: ").append(pgh.version).push_back('\n');
else if (!pgh.feature.empty()) else if (pgh.is_feature())
out_str.append("Feature: ").append(pgh.feature).push_back('\n'); out_str.append("Feature: ").append(pgh.feature).push_back('\n');
if (!pgh.depends.empty()) if (!pgh.depends.empty())
{ {

View File

@ -890,7 +890,7 @@ namespace vcpkg::Build
ExtendedBuildResult result = do_build_package_and_clean_buildtrees(paths, action); ExtendedBuildResult result = do_build_package_and_clean_buildtrees(paths, action);
fs.create_directories(abi_package_dir, ec); fs.create_directories(abi_package_dir, ec);
fs.copy_file(abi_file, abi_file_in_package, fs::stdfs::copy_options::none, ec); fs.copy_file(abi_file, abi_file_in_package, fs::copy_options::none, ec);
Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not copy into file: %s", abi_file_in_package.u8string()); Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not copy into file: %s", abi_file_in_package.u8string());
if (binary_caching_enabled && result.code == BuildResult::SUCCEEDED) if (binary_caching_enabled && result.code == BuildResult::SUCCEEDED)

View File

@ -17,6 +17,7 @@ namespace vcpkg::Commands
{ {
static std::vector<PackageNameAndFunction<CommandTypeA>> t = { static std::vector<PackageNameAndFunction<CommandTypeA>> t = {
{"install", &Install::perform_and_exit}, {"install", &Install::perform_and_exit},
{"x-set-installed", &SetInstalled::perform_and_exit},
{"ci", &CI::perform_and_exit}, {"ci", &CI::perform_and_exit},
{"remove", &Remove::perform_and_exit}, {"remove", &Remove::perform_and_exit},
{"upgrade", &Upgrade::perform_and_exit}, {"upgrade", &Upgrade::perform_and_exit},

View File

@ -0,0 +1,111 @@
#include "pch.h"
#include <vcpkg/base/system.print.h>
#include <vcpkg/commands.h>
#include <vcpkg/globalstate.h>
#include <vcpkg/help.h>
#include <vcpkg/input.h>
#include <vcpkg/install.h>
#include <vcpkg/remove.h>
#include <vcpkg/portfileprovider.h>
#include <vcpkg/vcpkglib.h>
namespace vcpkg::Commands::SetInstalled
{
const CommandStructure COMMAND_STRUCTURE = {
Help::create_example_string(R"(x-set-installed <package>...)"),
1,
SIZE_MAX,
{},
nullptr,
};
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
{
// input sanitization
const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
const std::vector<FullPackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
return Input::check_and_get_full_package_spec(
std::string(arg), default_triplet, COMMAND_STRUCTURE.example_text);
});
for (auto&& spec : specs)
{
Input::check_triplet(spec.package_spec.triplet(), paths);
}
const Build::BuildPackageOptions install_plan_options = {
Build::UseHeadVersion::NO,
Build::AllowDownloads::YES,
Build::OnlyDownloads::NO,
Build::CleanBuildtrees::YES,
Build::CleanPackages::YES,
Build::CleanDownloads::YES,
Build::DownloadTool::BUILT_IN,
GlobalState::g_binary_caching ? Build::BinaryCaching::YES : Build::BinaryCaching::NO,
Build::FailOnTombstone::NO,
};
PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports.get());
auto cmake_vars = CMakeVars::make_triplet_cmake_var_provider(paths);
// We have a set of user-requested specs.
// We need to know all the specs which are required to fulfill dependencies for those specs.
// Therefore, we see what we would install into an empty installed tree, so we can use the existing code.
auto action_plan = Dependencies::create_feature_install_plan(provider, *cmake_vars, specs, {});
for (auto&& action : action_plan.install_actions)
{
action.build_options = install_plan_options;
}
cmake_vars->load_tag_vars(action_plan, provider);
Build::compute_all_abis(paths, action_plan, *cmake_vars, {});
std::set<std::string> all_abis;
for (const auto& action : action_plan.install_actions) {
all_abis.insert(action.package_abi.value_or_exit(VCPKG_LINE_INFO));
}
// currently (or once) installed specifications
auto status_db = database_load_check(paths);
std::vector<PackageSpec> specs_to_remove;
for (auto&& status_pgh : status_db)
{
if (!status_pgh->is_installed()) continue;
if (status_pgh->package.is_feature()) continue;
const auto& abi = status_pgh->package.abi;
if (abi.empty() || !Util::Sets::contains(all_abis, abi))
{
specs_to_remove.push_back(status_pgh->package.spec);
}
}
auto remove_plan = Dependencies::create_remove_plan(specs_to_remove, status_db);
for (const auto& action : remove_plan)
{
Remove::perform_remove_plan_action(paths, action, Remove::Purge::NO, &status_db);
}
auto real_action_plan = Dependencies::create_feature_install_plan(provider, *cmake_vars, specs, status_db);
for (auto& action : real_action_plan.install_actions)
{
action.build_options = install_plan_options;
}
Dependencies::print_plan(real_action_plan, true);
const auto summary = Install::perform(real_action_plan, Install::KeepGoing::NO, paths, status_db, *cmake_vars);
System::print2("\nTotal elapsed time: ", summary.total_elapsed_time, "\n\n");
Checks::exit_success(VCPKG_LINE_INFO);
}
}

View File

@ -560,7 +560,7 @@ namespace vcpkg::Dependencies
? RequestType::USER_REQUESTED ? RequestType::USER_REQUESTED
: RequestType::AUTO_SELECTED; : RequestType::AUTO_SELECTED;
auto maybe_ipv = status_db.find_all_installed(spec); auto maybe_ipv = status_db.get_installed_package_view(spec);
if (auto p_ipv = maybe_ipv.get()) if (auto p_ipv = maybe_ipv.get())
{ {

View File

@ -34,7 +34,7 @@ namespace vcpkg::PortFileProvider
{ {
if (!overlay_path.empty()) if (!overlay_path.empty())
{ {
auto overlay = fs::stdfs::canonical(fs::u8path(overlay_path)); auto overlay = fs.canonical(VCPKG_LINE_INFO, fs::u8path(overlay_path));
Checks::check_exit(VCPKG_LINE_INFO, Checks::check_exit(VCPKG_LINE_INFO,
filesystem.exists(overlay), filesystem.exists(overlay),

View File

@ -21,7 +21,7 @@ namespace vcpkg::Remove
void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db) void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db)
{ {
auto& fs = paths.get_filesystem(); auto& fs = paths.get_filesystem();
auto maybe_ipv = status_db->find_all_installed(spec); auto maybe_ipv = status_db->get_installed_package_view(spec);
Checks::check_exit( Checks::check_exit(
VCPKG_LINE_INFO, maybe_ipv.has_value(), "unable to remove package %s: already removed", spec); VCPKG_LINE_INFO, maybe_ipv.has_value(), "unable to remove package %s: already removed", spec);
@ -72,6 +72,7 @@ namespace vcpkg::Remove
fs.remove(target, ec); fs.remove(target, ec);
if (ec) if (ec)
{ {
// TODO: this is racy; should we ignore this error?
#if defined(_WIN32) #if defined(_WIN32)
fs::stdfs::permissions(target, fs::perms::owner_all | fs::perms::group_all, ec); fs::stdfs::permissions(target, fs::perms::owner_all | fs::perms::group_all, ec);
fs.remove(target, ec); fs.remove(target, ec);

View File

@ -18,16 +18,16 @@ namespace vcpkg
{ {
if (p->package.spec.name() == name && p->package.spec.triplet() == triplet) if (p->package.spec.name() == name && p->package.spec.triplet() == triplet)
{ {
if (p->package.feature.empty()) if (p->package.is_feature())
spghs.emplace(spghs.begin(), &p);
else
spghs.emplace_back(&p); spghs.emplace_back(&p);
else
spghs.emplace(spghs.begin(), &p);
} }
} }
return spghs; return spghs;
} }
Optional<InstalledPackageView> StatusParagraphs::find_all_installed(const PackageSpec& spec) const Optional<InstalledPackageView> StatusParagraphs::get_installed_package_view(const PackageSpec& spec) const
{ {
InstalledPackageView ipv; InstalledPackageView ipv;
for (auto&& p : *this) for (auto&& p : *this)
@ -35,13 +35,12 @@ namespace vcpkg
if (p->package.spec.name() == spec.name() && p->package.spec.triplet() == spec.triplet() && if (p->package.spec.name() == spec.name() && p->package.spec.triplet() == spec.triplet() &&
p->is_installed()) p->is_installed())
{ {
if (p->package.feature.empty()) if (p->package.is_feature()) {
{ ipv.features.emplace_back(p.get());
} else {
Checks::check_exit(VCPKG_LINE_INFO, ipv.core == nullptr); Checks::check_exit(VCPKG_LINE_INFO, ipv.core == nullptr);
ipv.core = p.get(); ipv.core = p.get();
} }
else
ipv.features.emplace_back(p.get());
} }
} }
if (ipv.core != nullptr) if (ipv.core != nullptr)

View File

@ -152,6 +152,12 @@ namespace vcpkg
arg.substr(sizeof("--x-scripts-root=") - 1), "--x-scripts-root", args.scripts_root_dir); arg.substr(sizeof("--x-scripts-root=") - 1), "--x-scripts-root", args.scripts_root_dir);
continue; continue;
} }
if (Strings::starts_with(arg, "--x-install-root="))
{
parse_cojoined_value(
arg.substr(sizeof("--x-install-root=") - 1), "--x-install-root=", args.install_root_dir);
continue;
}
if (arg == "--triplet") if (arg == "--triplet")
{ {
++arg_begin; ++arg_begin;

View File

@ -178,7 +178,7 @@ namespace vcpkg
{ {
if (!pgh->is_installed()) continue; if (!pgh->is_installed()) continue;
auto& ipv = ipv_map[pgh->package.spec]; auto& ipv = ipv_map[pgh->package.spec];
if (pgh->package.feature.empty()) if (!pgh->package.is_feature())
{ {
ipv.core = pgh.get(); ipv.core = pgh.get();
} }
@ -206,7 +206,7 @@ namespace vcpkg
for (const std::unique_ptr<StatusParagraph>& pgh : status_db) for (const std::unique_ptr<StatusParagraph>& pgh : status_db)
{ {
if (!pgh->is_installed() || !pgh->package.feature.empty()) if (!pgh->is_installed() || pgh->package.is_feature())
{ {
continue; continue;
} }

View File

@ -14,6 +14,7 @@
namespace vcpkg namespace vcpkg
{ {
Expected<VcpkgPaths> VcpkgPaths::create(const fs::path& vcpkg_root_dir, Expected<VcpkgPaths> VcpkgPaths::create(const fs::path& vcpkg_root_dir,
const Optional<fs::path>& install_root_dir,
const Optional<fs::path>& vcpkg_scripts_root_dir, const Optional<fs::path>& vcpkg_scripts_root_dir,
const std::string& default_vs_path, const std::string& default_vs_path,
const std::vector<std::string>* triplets_dirs) const std::vector<std::string>* triplets_dirs)
@ -53,7 +54,7 @@ namespace vcpkg
asPath.u8string()); asPath.u8string());
} }
paths.downloads = fs::stdfs::canonical(std::move(asPath), ec); paths.downloads = fs.canonical(std::move(asPath), ec);
if (ec) if (ec)
{ {
return ec; return ec;
@ -65,13 +66,17 @@ namespace vcpkg
} }
paths.ports = paths.root / "ports"; paths.ports = paths.root / "ports";
paths.installed = paths.root / "installed"; if (auto d = install_root_dir.get()) {
paths.installed = fs.absolute(VCPKG_LINE_INFO, std::move(*d));
} else {
paths.installed = paths.root / "installed";
}
paths.triplets = paths.root / "triplets"; paths.triplets = paths.root / "triplets";
paths.community_triplets = paths.triplets / "community"; paths.community_triplets = paths.triplets / "community";
if (auto scripts_dir = vcpkg_scripts_root_dir.get()) if (auto scripts_dir = vcpkg_scripts_root_dir.get())
{ {
if (scripts_dir->empty() || !fs::stdfs::is_directory(*scripts_dir)) if (scripts_dir->empty() || !fs::is_directory(fs.status(VCPKG_LINE_INFO, *scripts_dir)))
{ {
Metrics::g_metrics.lock()->track_property("error", "Invalid scripts override directory."); Metrics::g_metrics.lock()->track_property("error", "Invalid scripts override directory.");
Checks::exit_with_message( Checks::exit_with_message(
@ -108,11 +113,11 @@ namespace vcpkg
paths.get_filesystem().exists(path), paths.get_filesystem().exists(path),
"Error: Path does not exist '%s'", "Error: Path does not exist '%s'",
triplets_dir); triplets_dir);
paths.triplets_dirs.emplace_back(fs::stdfs::canonical(path)); paths.triplets_dirs.emplace_back(fs.canonical(VCPKG_LINE_INFO, path));
} }
} }
paths.triplets_dirs.emplace_back(fs::stdfs::canonical(paths.triplets)); paths.triplets_dirs.emplace_back(fs.canonical(VCPKG_LINE_INFO, paths.triplets));
paths.triplets_dirs.emplace_back(fs::stdfs::canonical(paths.community_triplets)); paths.triplets_dirs.emplace_back(fs.canonical(VCPKG_LINE_INFO, paths.community_triplets));
return paths; return paths;
} }

View File

@ -253,6 +253,7 @@
<ClCompile Include="..\src\vcpkg\commands.porthistory.cpp" /> <ClCompile Include="..\src\vcpkg\commands.porthistory.cpp" />
<ClCompile Include="..\src\vcpkg\commands.portsdiff.cpp" /> <ClCompile Include="..\src\vcpkg\commands.portsdiff.cpp" />
<ClCompile Include="..\src\vcpkg\commands.search.cpp" /> <ClCompile Include="..\src\vcpkg\commands.search.cpp" />
<ClCompile Include="..\src\vcpkg\commands.setinstalled.cpp" />
<ClCompile Include="..\src\vcpkg\commands.upgrade.cpp" /> <ClCompile Include="..\src\vcpkg\commands.upgrade.cpp" />
<ClCompile Include="..\src\vcpkg\commands.version.cpp" /> <ClCompile Include="..\src\vcpkg\commands.version.cpp" />
<ClCompile Include="..\src\vcpkg\commands.xvsinstances.cpp" /> <ClCompile Include="..\src\vcpkg\commands.xvsinstances.cpp" />

View File

@ -87,6 +87,9 @@
<ClCompile Include="..\src\vcpkg\commands.search.cpp"> <ClCompile Include="..\src\vcpkg\commands.search.cpp">
<Filter>Source Files\vcpkg</Filter> <Filter>Source Files\vcpkg</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\vcpkg\commands.setinstalled.cpp">
<Filter>Source Files\vcpkg</Filter>
</ClCompile>
<ClCompile Include="..\src\vcpkg\commands.version.cpp"> <ClCompile Include="..\src\vcpkg\commands.version.cpp">
<Filter>Source Files\vcpkg</Filter> <Filter>Source Files\vcpkg</Filter>
</ClCompile> </ClCompile>
@ -441,4 +444,4 @@
<Filter>Header Files\vcpkg</Filter> <Filter>Header Files\vcpkg</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>