diff options
Diffstat (limited to 'toolsrc/src/vcpkg.cpp')
| -rw-r--r-- | toolsrc/src/vcpkg.cpp | 282 |
1 files changed, 186 insertions, 96 deletions
diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 154aefd0a..ac2eec876 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -1,77 +1,148 @@ +#if defined(_WIN32) #define WIN32_LEAN_AND_MEAN #include <Windows.h> -#include "Paragraphs.h" -#include "metrics.h" -#include "vcpkg_Chrono.h" -#include "vcpkg_Commands.h" -#include "vcpkg_Files.h" -#include "vcpkg_Input.h" -#include "vcpkg_Strings.h" -#include "vcpkg_System.h" -#include "vcpkglib.h" -#include <Shlobj.h> +#pragma warning(push) +#pragma warning(disable : 4768) +#include <ShlObj.h> +#pragma warning(pop) +#else +#include <unistd.h> +#endif + +#include <vcpkg/base/chrono.h> +#include <vcpkg/base/files.h> +#include <vcpkg/base/strings.h> +#include <vcpkg/base/system.h> +#include <vcpkg/commands.h> +#include <vcpkg/globalstate.h> +#include <vcpkg/help.h> +#include <vcpkg/input.h> +#include <vcpkg/metrics.h> +#include <vcpkg/paragraphs.h> +#include <vcpkg/userconfig.h> +#include <vcpkg/vcpkglib.h> + #include <cassert> #include <fstream> #include <memory> +#include <random> + +#pragma comment(lib, "ole32") +#pragma comment(lib, "shell32") using namespace vcpkg; void invalid_command(const std::string& cmd) { System::println(System::Color::error, "invalid command: %s", cmd); - Commands::Help::print_usage(); + Help::print_usage(); Checks::exit_fail(VCPKG_LINE_INFO); } static void inner(const VcpkgCmdArguments& args) { - Metrics::track_property("command", args.command); + Metrics::g_metrics.lock()->track_property("command", args.command); if (args.command.empty()) { - Commands::Help::print_usage(); + Help::print_usage(); Checks::exit_fail(VCPKG_LINE_INFO); } - if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_c())) + static const auto find_command = [&](auto&& commands) { + auto it = Util::find_if(commands, [&](auto&& commandc) { + return Strings::case_insensitive_ascii_equals(commandc.name, args.command); + }); + using std::end; + if (it != end(commands)) + { + return &*it; + } + else + return static_cast<decltype(&*it)>(nullptr); + }; + + if (const auto command_function = find_command(Commands::get_available_commands_type_c())) { - return command_function(args); + return command_function->function(args); } fs::path vcpkg_root_dir; if (args.vcpkg_root_dir != nullptr) { - vcpkg_root_dir = fs::stdfs::absolute(Strings::to_utf16(*args.vcpkg_root_dir)); + vcpkg_root_dir = fs::stdfs::absolute(fs::u8path(*args.vcpkg_root_dir)); } else { - const Optional<std::wstring> vcpkg_root_dir_env = System::get_environment_variable(L"VCPKG_ROOT"); - if (auto v = vcpkg_root_dir_env.get()) + const auto vcpkg_root_dir_env = System::get_environment_variable("VCPKG_ROOT"); + if (const auto v = vcpkg_root_dir_env.get()) { vcpkg_root_dir = fs::stdfs::absolute(*v); } else { - vcpkg_root_dir = Files::get_real_filesystem().find_file_recursively_up( - fs::stdfs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root"); + const fs::path current_path = fs::stdfs::current_path(); + vcpkg_root_dir = Files::get_real_filesystem().find_file_recursively_up(current_path, ".vcpkg-root"); + + if (vcpkg_root_dir.empty()) + { + vcpkg_root_dir = Files::get_real_filesystem().find_file_recursively_up( + fs::stdfs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root"); + } } } Checks::check_exit(VCPKG_LINE_INFO, !vcpkg_root_dir.empty(), "Error: Could not detect vcpkg-root."); - const Expected<VcpkgPaths> expected_paths = VcpkgPaths::create(vcpkg_root_dir); + Debug::println("Using vcpkg-root: %s", vcpkg_root_dir.u8string()); + + auto default_vs_path = System::get_environment_variable("VCPKG_DEFAULT_VS_PATH").value_or(""); + + const Expected<VcpkgPaths> expected_paths = VcpkgPaths::create(vcpkg_root_dir, default_vs_path); Checks::check_exit(VCPKG_LINE_INFO, - !expected_paths.error_code(), + !expected_paths.error(), "Error: Invalid vcpkg root directory %s: %s", vcpkg_root_dir.string(), - expected_paths.error_code().message()); + expected_paths.error().message()); const VcpkgPaths paths = expected_paths.value_or_exit(VCPKG_LINE_INFO); - int exit_code = _wchdir(paths.root.c_str()); + +#if defined(_WIN32) + const int exit_code = _wchdir(paths.root.c_str()); +#else + const int exit_code = chdir(paths.root.c_str()); +#endif Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed"); - if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_b())) + if (args.command != "autocomplete") + { + Commands::Version::warn_if_vcpkg_version_mismatch(paths); + std::string surveydate = *GlobalState::g_surveydate.lock(); + auto maybe_surveydate = Chrono::CTime::parse(surveydate); + if (auto p_surveydate = maybe_surveydate.get()) + { + auto delta = std::chrono::system_clock::now() - p_surveydate->to_time_point(); + // 24 hours/day * 30 days/month + if (std::chrono::duration_cast<std::chrono::hours>(delta).count() > 24 * 30) + { + std::default_random_engine generator( + static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count())); + std::uniform_int_distribution<int> distribution(1, 4); + + if (distribution(generator) == 1) + { + Metrics::g_metrics.lock()->track_property("surveyprompt", "true"); + System::println( + System::Color::success, + "Your feedback is important to improve Vcpkg! Please take 3 minutes to complete our survey " + "by running: vcpkg contact --survey"); + } + } + } + } + + if (const auto command_function = find_command(Commands::get_available_commands_type_b())) { - return command_function(args, paths); + return command_function->function(args, paths); } Triplet default_triplet; @@ -81,92 +152,84 @@ static void inner(const VcpkgCmdArguments& args) } else { - const Optional<std::wstring> vcpkg_default_triplet_env = - System::get_environment_variable(L"VCPKG_DEFAULT_TRIPLET"); - if (auto v = vcpkg_default_triplet_env.get()) + const auto vcpkg_default_triplet_env = System::get_environment_variable("VCPKG_DEFAULT_TRIPLET"); + if (const auto v = vcpkg_default_triplet_env.get()) { - default_triplet = Triplet::from_canonical_name(Strings::to_utf8(*v)); + default_triplet = Triplet::from_canonical_name(*v); } else { +#if defined(_WIN32) default_triplet = Triplet::X86_WINDOWS; +#elif defined(__APPLE__) + default_triplet = Triplet::from_canonical_name("x64-osx"); +#elif defined(__FreeBSD__) + default_triplet = Triplet::from_canonical_name("x64-freebsd"); +#else + default_triplet = Triplet::from_canonical_name("x64-linux"); +#endif } } Input::check_triplet(default_triplet, paths); - if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_a())) + if (const auto command_function = find_command(Commands::get_available_commands_type_a())) { - return command_function(args, paths, default_triplet); + return command_function->function(args, paths, default_triplet); } return invalid_command(args.command); } -static void loadConfig() +static void load_config() { - fs::path localappdata; - { - // Config path in AppDataLocal - wchar_t* localappdatapath = nullptr; - if (S_OK != SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &localappdatapath)) __fastfail(1); - localappdata = localappdatapath; - CoTaskMemFree(localappdatapath); - } + auto& fs = Files::get_real_filesystem(); - try - { - auto maybe_pghs = Paragraphs::get_paragraphs(Files::get_real_filesystem(), localappdata / "vcpkg" / "config"); - if (auto p_pghs = maybe_pghs.get()) - { - const auto& pghs = *p_pghs; + auto config = UserConfig::try_read_data(fs); - std::unordered_map<std::string, std::string> keys; - if (pghs.size() > 0) keys = pghs[0]; + bool write_config = false; - for (size_t x = 1; x < pghs.size(); ++x) - { - for (auto&& p : pghs[x]) - keys.insert(p); - } + // config file not found, could not be read, or invalid + if (config.user_id.empty() || config.user_time.empty()) + { + ::vcpkg::Metrics::Metrics::init_user_information(config.user_id, config.user_time); + write_config = true; + } - auto user_id = keys["User-Id"]; - auto user_time = keys["User-Since"]; - if (!user_id.empty() && !user_time.empty()) - { - Metrics::set_user_information(user_id, user_time); - return; - } - } +#if defined(_WIN32) + if (config.user_mac.empty()) + { + config.user_mac = Metrics::get_MAC_user(); + write_config = true; } - catch (...) +#endif + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->set_user_information(config.user_id, config.user_time); +#if defined(_WIN32) + locked_metrics->track_property("user_mac", config.user_mac); +#endif } - // config file not found, could not be read, or invalid - std::string user_id, user_time; - Metrics::init_user_information(user_id, user_time); - Metrics::set_user_information(user_id, user_time); - try + if (config.last_completed_survey.empty()) { - std::error_code ec; - auto& fs = Files::get_real_filesystem(); - fs.create_directory(localappdata / "vcpkg", ec); - fs.write_contents(localappdata / "vcpkg" / "config", - Strings::format("User-Id: %s\n" - "User-Since: %s\n", - user_id, - user_time)); + config.last_completed_survey = config.user_time; } - catch (...) + + GlobalState::g_surveydate.lock()->assign(config.last_completed_survey); + + if (write_config) { + config.try_write_data(fs); } } +#if defined(_WIN32) static std::string trim_path_from_command_line(const std::string& full_command_line) { Checks::check_exit( - VCPKG_LINE_INFO, full_command_line.size() > 0, "Internal failure - cannot have empty command line"); + VCPKG_LINE_INFO, !full_command_line.empty(), "Internal failure - cannot have empty command line"); if (full_command_line[0] == '"') { @@ -183,35 +246,56 @@ static std::string trim_path_from_command_line(const std::string& full_command_l ++it; return std::string(it, full_command_line.cend()); } +#endif -static ElapsedTime g_timer; - +#if defined(_WIN32) int wmain(const int argc, const wchar_t* const* const argv) +#else +int main(const int argc, const char* const* const argv) +#endif { if (argc == 0) std::abort(); - g_timer = ElapsedTime::create_started(); - atexit([]() { - auto elapsed_us = g_timer.microseconds(); - Metrics::track_metric("elapsed_us", elapsed_us); - g_debugging = false; - Metrics::flush(); - }); + *GlobalState::timer.lock() = Chrono::ElapsedTimer::create_started(); - Metrics::track_property("version", Commands::Version::version()); +#if defined(_WIN32) + GlobalState::g_init_console_cp = GetConsoleCP(); + GlobalState::g_init_console_output_cp = GetConsoleOutputCP(); + + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); const std::string trimmed_command_line = trim_path_from_command_line(Strings::to_utf8(GetCommandLineW())); - Metrics::track_property("cmdline", trimmed_command_line); - loadConfig(); - Metrics::track_property("sqmuser", Metrics::get_SQM_user()); +#endif + + { + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_property("version", Commands::Version::version()); +#if defined(_WIN32) + locked_metrics->track_property("cmdline", trimmed_command_line); +#endif + } + load_config(); + + const auto vcpkg_feature_flags_env = System::get_environment_variable("VCPKG_FEATURE_FLAGS"); + if (const auto v = vcpkg_feature_flags_env.get()) + { + auto flags = Strings::split(*v, ","); + if (std::find(flags.begin(), flags.end(), "binarycaching") != flags.end()) GlobalState::g_binary_caching = true; + } const VcpkgCmdArguments args = VcpkgCmdArguments::create_from_command_line(argc, argv); - if (auto p = args.printmetrics.get()) Metrics::set_print_metrics(*p); - if (auto p = args.sendmetrics.get()) Metrics::set_send_metrics(*p); - if (auto p = args.debug.get()) g_debugging = *p; + if (const auto p = args.featurepackages.get()) GlobalState::feature_packages = *p; + if (const auto p = args.binarycaching.get()) GlobalState::g_binary_caching = *p; + + if (const auto p = args.printmetrics.get()) Metrics::g_metrics.lock()->set_print_metrics(*p); + if (const auto p = args.sendmetrics.get()) Metrics::g_metrics.lock()->set_send_metrics(*p); + if (const auto p = args.debug.get()) GlobalState::debugging = *p; - if (g_debugging) + Checks::register_console_ctrl_handler(); + + if (GlobalState::debugging) { inner(args); Checks::exit_fail(VCPKG_LINE_INFO); @@ -231,7 +315,7 @@ int wmain(const int argc, const wchar_t* const* const argv) { exc_msg = "unknown error(...)"; } - Metrics::track_property("error", exc_msg); + Metrics::g_metrics.lock()->track_property("error", exc_msg); fflush(stdout); System::print("vcpkg.exe has crashed.\n" @@ -247,6 +331,12 @@ int wmain(const int argc, const wchar_t* const* const argv) exc_msg); fflush(stdout); for (int x = 0; x < argc; ++x) + { +#if defined(_WIN32) System::println("%s|", Strings::to_utf8(argv[x])); +#else + System::println("%s|", argv[x]); +#endif + } fflush(stdout); } |
