From 91da4aab4c74af1d30c68896a058100257910e8d Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 2 Jul 2019 05:51:07 +0000 Subject: [PATCH] Allow redirection of the scripts folder. (#6552) * Allow redirection of the scripts folder with an environment variable. * - Updated feature from environment variable to argument. * Fix crash when no scripts override is given and use --scripts-root= format * Update help messages to use --scripts-root= format --- toolsrc/include/vcpkg/vcpkgcmdarguments.h | 1 + toolsrc/include/vcpkg/vcpkgpaths.h | 3 +- toolsrc/src/tests.arguments.cpp | 6 ++- toolsrc/src/vcpkg.cpp | 10 +++++ toolsrc/src/vcpkg/help.cpp | 2 + toolsrc/src/vcpkg/vcpkgcmdarguments.cpp | 30 ++++++++++++- toolsrc/src/vcpkg/vcpkgpaths.cpp | 53 +++++++++++++++-------- 7 files changed, 83 insertions(+), 22 deletions(-) diff --git a/toolsrc/include/vcpkg/vcpkgcmdarguments.h b/toolsrc/include/vcpkg/vcpkgcmdarguments.h index ff13ae6bf61e3a..fe7911ae3fba31 100644 --- a/toolsrc/include/vcpkg/vcpkgcmdarguments.h +++ b/toolsrc/include/vcpkg/vcpkgcmdarguments.h @@ -86,6 +86,7 @@ namespace vcpkg static VcpkgCmdArguments create_from_arg_sequence(const std::string* arg_begin, const std::string* arg_end); std::unique_ptr vcpkg_root_dir; + std::unique_ptr scripts_root_dir; std::unique_ptr triplet; std::unique_ptr> overlay_ports; std::unique_ptr> overlay_triplets; diff --git a/toolsrc/include/vcpkg/vcpkgpaths.h b/toolsrc/include/vcpkg/vcpkgpaths.h index a30e0c65349354..ce442858bd3616 100644 --- a/toolsrc/include/vcpkg/vcpkgpaths.h +++ b/toolsrc/include/vcpkg/vcpkgpaths.h @@ -47,7 +47,8 @@ namespace vcpkg struct VcpkgPaths { - static Expected create(const fs::path& vcpkg_root_dir, + static Expected create(const fs::path& vcpkg_root_dir, + const Optional& vcpkg_scripts_root_dir, const std::string& default_vs_path, const std::vector* triplets_dirs); diff --git a/toolsrc/src/tests.arguments.cpp b/toolsrc/src/tests.arguments.cpp index 51ababd3db4f7e..533b3a0d0a63f7 100644 --- a/toolsrc/src/tests.arguments.cpp +++ b/toolsrc/src/tests.arguments.cpp @@ -15,9 +15,10 @@ namespace UnitTest1 { TEST_METHOD(create_from_arg_sequence_options_lower) { - std::vector t = {"--vcpkg-root", "C:\\vcpkg", "--debug", "--sendmetrics", "--printmetrics"}; + std::vector t = {"--vcpkg-root", "C:\\vcpkg", "--scripts-root", "C:\\scripts", "--debug", "--sendmetrics", "--printmetrics"}; auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); Assert::AreEqual("C:\\vcpkg", v.vcpkg_root_dir.get()->c_str()); + Assert::AreEqual("C:\\scripts", v.scripts_root_dir.get()->c_str()); Assert::IsTrue(v.debug && *v.debug.get()); Assert::IsTrue(v.sendmetrics && v.sendmetrics.get()); Assert::IsTrue(v.printmetrics && *v.printmetrics.get()); @@ -25,9 +26,10 @@ namespace UnitTest1 TEST_METHOD(create_from_arg_sequence_options_upper) { - std::vector t = {"--VCPKG-ROOT", "C:\\vcpkg", "--DEBUG", "--SENDMETRICS", "--PRINTMETRICS"}; + std::vector t = {"--VCPKG-ROOT", "C:\\vcpkg", "--SCRIPTS-ROOT", "C:\\scripts", "--DEBUG", "--SENDMETRICS", "--PRINTMETRICS"}; auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size()); Assert::AreEqual("C:\\vcpkg", v.vcpkg_root_dir.get()->c_str()); + Assert::AreEqual("C:\\scripts", v.scripts_root_dir.get()->c_str()); Assert::IsTrue(v.debug && *v.debug.get()); Assert::IsTrue(v.sendmetrics && v.sendmetrics.get()); Assert::IsTrue(v.printmetrics && *v.printmetrics.get()); diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 5da97b136d4d9f..363b398146ab2b 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -116,9 +116,19 @@ static void inner(const VcpkgCmdArguments& args) Debug::print("Using vcpkg-root: ", vcpkg_root_dir.u8string(), '\n'); + Optional vcpkg_scripts_root_dir = nullopt; + if (nullptr != args.scripts_root_dir) + { + vcpkg_scripts_root_dir = fs::stdfs::canonical(fs::u8path(*args.scripts_root_dir)); + 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(""); + + const Expected expected_paths = VcpkgPaths::create(vcpkg_root_dir, + vcpkg_scripts_root_dir, default_vs_path, args.overlay_triplets.get()); Checks::check_exit(VCPKG_LINE_INFO, diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index 896f62661fd1f0..9b2751739f939d 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -124,6 +124,8 @@ namespace vcpkg::Help " (default: " ENVVAR(VCPKG_ROOT) // ")\n" "\n" + " --scripts-root= Specify the scripts root directory\n" + "\n" " @response_file Specify a " "response file to provide additional parameters\n" "\n" diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp index 3c1452d475a8e9..7a28fb571a03a8 100644 --- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp +++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp @@ -33,6 +33,21 @@ namespace vcpkg option_field = std::make_unique(*arg_begin); } + static void parse_cojoined_value(std::string new_value, + const std::string& option_name, + std::unique_ptr& option_field) + { + if (nullptr != option_field) + { + System::printf(System::Color::error, "Error: %s specified multiple times\n", option_name); + Metrics::g_metrics.lock()->track_property("error", "error option specified multiple times"); + Help::print_usage(); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + option_field = std::make_unique(std::move(new_value)); + } + static void parse_switch(bool new_setting, const std::string& option_name, Optional& option_field) { if (option_field && option_field != new_setting) @@ -120,9 +135,10 @@ namespace vcpkg if (arg[0] == '-' && arg[1] == '-') { - // make argument case insensitive + // make argument case insensitive before the first = auto& f = std::use_facet>(std::locale()); - f.tolower(&arg[0], &arg[0] + arg.size()); + auto first_eq = std::find(std::begin(arg), std::end(arg), '='); + f.tolower(&arg[0], &arg[0] + (first_eq - std::begin(arg))); // command switch if (arg == "--vcpkg-root") { @@ -130,6 +146,13 @@ namespace vcpkg parse_value(arg_begin, arg_end, "--vcpkg-root", args.vcpkg_root_dir); continue; } + if (Strings::starts_with(arg, "--scripts-root=")) + { + parse_cojoined_value(arg.substr(sizeof("--scripts-root=") - 1), + "--scripts-root", + args.scripts_root_dir); + continue; + } if (arg == "--triplet") { ++arg_begin; @@ -411,5 +434,8 @@ namespace vcpkg System::printf(" %-40s %s\n", "--vcpkg-root ", "Specify the vcpkg directory to use instead of current directory or tool directory"); + System::printf(" %-40s %s\n", + "--scripts-root=", + "Specify the scripts directory to use instead of default vcpkg scripts directory"); } } diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index 909fbeb4487b5f..d16acf2e8b1ec5 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -13,7 +13,8 @@ namespace vcpkg { - Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir, + Expected VcpkgPaths::create(const fs::path& vcpkg_root_dir, + const Optional& vcpkg_scripts_root_dir, const std::string& default_vs_path, const std::vector* triplets_dirs) { @@ -65,7 +66,25 @@ namespace vcpkg paths.ports = paths.root / "ports"; paths.installed = paths.root / "installed"; paths.triplets = paths.root / "triplets"; - paths.scripts = paths.root / "scripts"; + + if (auto scripts_dir = vcpkg_scripts_root_dir.get()) + { + if (scripts_dir->empty() || !fs::stdfs::is_directory(*scripts_dir)) + { + Metrics::g_metrics.lock()->track_property("error", "Invalid scripts override directory."); + Checks::exit_with_message( + VCPKG_LINE_INFO, + "Invalid scripts override directory: %s; " + "create that directory or unset --scripts-root to use the default scripts location.", + scripts_dir->u8string()); + } + + paths.scripts = *scripts_dir; + } + else + { + paths.scripts = paths.root / "scripts"; + } paths.tools = paths.downloads / "tools"; paths.buildsystems = paths.scripts / "buildsystems"; @@ -132,21 +151,21 @@ namespace vcpkg } const fs::path VcpkgPaths::get_triplet_file_path(const Triplet& triplet) const - { - return m_triplets_cache.get_lazy(triplet, [&]()-> auto { - for (auto&& triplet_dir : triplets_dirs) - { - auto&& path = triplet_dir / (triplet.canonical_name() + ".cmake"); - if (this->get_filesystem().exists(path)) - { - return path; - } - } - - Checks::exit_with_message(VCPKG_LINE_INFO, - "Error: Triplet file %s.cmake not found", - triplet.canonical_name()); - }); + { + return m_triplets_cache.get_lazy(triplet, [&]()-> auto { + for (auto&& triplet_dir : triplets_dirs) + { + auto&& path = triplet_dir / (triplet.canonical_name() + ".cmake"); + if (this->get_filesystem().exists(path)) + { + return path; + } + } + + Checks::exit_with_message(VCPKG_LINE_INFO, + "Error: Triplet file %s.cmake not found", + triplet.canonical_name()); + }); }