aboutsummaryrefslogtreecommitdiff
path: root/toolsrc
diff options
context:
space:
mode:
authorras0219 <533828+ras0219@users.noreply.github.com>2020-12-10 20:54:34 -0800
committerGitHub <noreply@github.com>2020-12-10 20:54:34 -0800
commitc2329ab26a6e9e06da101d8541c393c102ba6c8c (patch)
tree762cd489a062a85b218e67e4256edef22daec934 /toolsrc
parentc30903782c88967652178486a5f3e490fb2e8143 (diff)
downloadvcpkg-c2329ab26a6e9e06da101d8541c393c102ba6c8c.tar.gz
vcpkg-c2329ab26a6e9e06da101d8541c393c102ba6c8c.zip
[vcpkg] Improve error messages for incomplete Mono (#14948)
* [vcpkg] Improve error messages for incomplete Mono * [vcpkg] Add mono upgrade notice for Ubuntu 18.04 users * [vcpkg] Fix always failing to check CMake version due to preferring 'error' constructor in ExpectedS * [vcpkg] Eagerly display the 'Ubuntu needs new mono' message to avoid users needing to install it twice Co-authored-by: Robert Schumacher <roschuma@microsoft.com>
Diffstat (limited to 'toolsrc')
-rw-r--r--toolsrc/include/vcpkg/base/expected.h5
-rw-r--r--toolsrc/src/vcpkg/tools.cpp111
2 files changed, 78 insertions, 38 deletions
diff --git a/toolsrc/include/vcpkg/base/expected.h b/toolsrc/include/vcpkg/base/expected.h
index 12bb64727..13e7b4bcb 100644
--- a/toolsrc/include/vcpkg/base/expected.h
+++ b/toolsrc/include/vcpkg/base/expected.h
@@ -110,7 +110,10 @@ namespace vcpkg
// Constructors are intentionally implicit
ExpectedT(const S& s, ExpectedRightTag = {}) : m_s(s) { }
- ExpectedT(S&& s, ExpectedRightTag = {}) : m_s(std::move(s)) { }
+ template<class = std::enable_if<!std::is_reference<S>::value>>
+ ExpectedT(S&& s, ExpectedRightTag = {}) : m_s(std::move(s))
+ {
+ }
ExpectedT(const T& t, ExpectedLeftTag = {}) : m_t(t) { }
template<class = std::enable_if<!std::is_reference<T>::value>>
diff --git a/toolsrc/src/vcpkg/tools.cpp b/toolsrc/src/vcpkg/tools.cpp
index 69ad05d38..0b82e7780 100644
--- a/toolsrc/src/vcpkg/tools.cpp
+++ b/toolsrc/src/vcpkg/tools.cpp
@@ -83,12 +83,23 @@ namespace vcpkg
const bool has_tool_entry = std::regex_search(XML.cbegin(), XML.cend(), match_tool_entry, tool_regex);
if (!has_tool_entry)
{
+ StringLiteral add_info = "";
+ if (tool == "mono")
+ {
+#if defined(__APPLE__)
+ add_info = " (brew install mono)";
+#else
+ add_info = " (e.g. sudo apt install mono-complete). Ubuntu 18.04 users may "
+ "need a newer version of mono, available at https://www.mono-project.com/download/stable/";
+#endif
+ }
return Strings::format("Could not automatically acquire %s because there is no entry in %s for os=%s. You "
- "may be able to install %s via your system package manager.",
+ "may be able to install %s via your system package manager%s.",
tool,
fs::u8string(XML_PATH),
OS_STRING,
- tool);
+ tool,
+ add_info);
}
const std::string tool_data =
@@ -139,7 +150,7 @@ namespace vcpkg
virtual std::array<int, 3> default_min_version() const = 0;
virtual void add_special_paths(std::vector<fs::path>& out_candidate_paths) const { (void)out_candidate_paths; }
- virtual Optional<std::string> get_version(const VcpkgPaths& paths, const fs::path& path_to_exe) const = 0;
+ virtual ExpectedS<std::string> get_version(const VcpkgPaths& paths, const fs::path& path_to_exe) const = 0;
};
static Optional<PathAndVersion> find_first_with_sufficient_version(const VcpkgPaths& paths,
@@ -222,10 +233,9 @@ namespace vcpkg
const ToolProvider& tool_provider,
const ToolData& tool_data)
{
- const auto downloaded_path = fetch_tool(paths, tool_provider.tool_data_name(), tool_data);
- const auto downloaded_version =
- tool_provider.get_version(paths, downloaded_path).value_or_exit(VCPKG_LINE_INFO);
- return {downloaded_path, downloaded_version};
+ auto downloaded_path = fetch_tool(paths, tool_provider.tool_data_name(), tool_data);
+ auto downloaded_version = tool_provider.get_version(paths, downloaded_path).value_or_exit(VCPKG_LINE_INFO);
+ return {std::move(downloaded_path), std::move(downloaded_version)};
}
static PathAndVersion get_path(const VcpkgPaths& paths, const ToolProvider& tool)
@@ -285,13 +295,15 @@ namespace vcpkg
(void)out_candidate_paths;
#endif
}
- virtual Optional<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
+ virtual ExpectedS<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
{
const std::string cmd = Strings::format(R"("%s" --version)", fs::u8string(path_to_exe));
- const auto rc = System::cmd_execute_and_capture_output(cmd);
+ auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
- return nullopt;
+ return {Strings::concat(
+ std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
+ expected_right_tag};
}
/* Sample output:
@@ -299,7 +311,8 @@ cmake version 3.10.2
CMake suite maintained and supported by Kitware (kitware.com/cmake).
*/
- return StringView::find_exactly_one_enclosed(rc.output, "cmake version ", "\n").to_string();
+ return {StringView::find_exactly_one_enclosed(rc.output, "cmake version ", "\n").to_string(),
+ expected_left_tag};
}
};
@@ -311,19 +324,21 @@ CMake suite maintained and supported by Kitware (kitware.com/cmake).
virtual const std::string& exe_stem() const override { return m_exe; }
virtual std::array<int, 3> default_min_version() const override { return {3, 5, 1}; }
- virtual Optional<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
+ virtual ExpectedS<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
{
const std::string cmd = Strings::format(R"("%s" --version)", fs::u8string(path_to_exe));
- const auto rc = System::cmd_execute_and_capture_output(cmd);
+ auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
- return nullopt;
+ return {Strings::concat(
+ std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
+ expected_right_tag};
}
/* Sample output:
1.8.2
*/
- return rc.output;
+ return {std::move(rc.output), expected_left_tag};
}
};
@@ -335,7 +350,7 @@ CMake suite maintained and supported by Kitware (kitware.com/cmake).
virtual const std::string& exe_stem() const override { return m_exe; }
virtual std::array<int, 3> default_min_version() const override { return {4, 6, 2}; }
- virtual Optional<std::string> get_version(const VcpkgPaths& paths, const fs::path& path_to_exe) const override
+ virtual ExpectedS<std::string> get_version(const VcpkgPaths& paths, const fs::path& path_to_exe) const override
{
System::CmdLineBuilder cmd;
#ifndef _WIN32
@@ -344,10 +359,23 @@ CMake suite maintained and supported by Kitware (kitware.com/cmake).
(void)paths;
#endif
cmd.path_arg(path_to_exe);
- const auto rc = System::cmd_execute_and_capture_output(cmd.extract());
+ auto rc = System::cmd_execute_and_capture_output(cmd.extract());
if (rc.exit_code != 0)
{
- return nullopt;
+#ifndef _WIN32
+ return {Strings::concat(
+ std::move(rc.output),
+ "\n\nFailed to get version of ",
+ fs::u8string(path_to_exe),
+ "\nThis may be caused by an incomplete mono installation. Full mono is "
+ "available on some systems via `sudo apt install mono-complete`. Ubuntu 18.04 users may "
+ "need a newer version of mono, available at https://www.mono-project.com/download/stable/"),
+ expected_right_tag};
+#else
+ return {Strings::concat(
+ std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
+ expected_right_tag};
+#endif
}
/* Sample output:
@@ -357,7 +385,8 @@ Type 'NuGet help <command>' for help on a specific command.
[[[List of available commands follows]]]
*/
- return StringView::find_exactly_one_enclosed(rc.output, "NuGet Version: ", "\n").to_string();
+ return {StringView::find_exactly_one_enclosed(rc.output, "NuGet Version: ", "\n").to_string(),
+ expected_left_tag};
}
};
@@ -383,13 +412,15 @@ Type 'NuGet help <command>' for help on a specific command.
#endif
}
- virtual Optional<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
+ virtual ExpectedS<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
{
const std::string cmd = Strings::format(R"("%s" --version)", fs::u8string(path_to_exe));
- const auto rc = System::cmd_execute_and_capture_output(cmd);
+ auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
- return nullopt;
+ return {Strings::concat(
+ std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
+ expected_right_tag};
}
/* Sample output:
@@ -398,7 +429,7 @@ git version 2.17.1.windows.2
const auto idx = rc.output.find("git version ");
Checks::check_exit(
VCPKG_LINE_INFO, idx != std::string::npos, "Unexpected format of git version string: %s", rc.output);
- return rc.output.substr(idx);
+ return {rc.output.substr(idx), expected_left_tag};
}
};
@@ -410,13 +441,15 @@ git version 2.17.1.windows.2
virtual const std::string& exe_stem() const override { return m_exe; }
virtual std::array<int, 3> default_min_version() const override { return {0, 0, 0}; }
- virtual Optional<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
+ virtual ExpectedS<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
{
- const auto rc = System::cmd_execute_and_capture_output(
+ auto rc = System::cmd_execute_and_capture_output(
System::CmdLineBuilder().path_arg(path_to_exe).string_arg("--version").extract());
if (rc.exit_code != 0)
{
- return nullopt;
+ return {Strings::concat(
+ std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
+ expected_right_tag};
}
/* Sample output:
@@ -425,7 +458,7 @@ Mono JIT compiler version 6.8.0.105 (Debian 6.8.0.105+dfsg-2 Wed Feb 26 23:23:50
const auto idx = rc.output.find("Mono JIT compiler version ");
Checks::check_exit(
VCPKG_LINE_INFO, idx != std::string::npos, "Unexpected format of mono version string: %s", rc.output);
- return rc.output.substr(idx);
+ return {rc.output.substr(idx), expected_left_tag};
}
};
@@ -450,19 +483,21 @@ Mono JIT compiler version 6.8.0.105 (Debian 6.8.0.105+dfsg-2 Wed Feb 26 23:23:50
// "Qt" / "QtIFW-3.1.0" / "bin" / "installerbase.exe");
}
- virtual Optional<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
+ virtual ExpectedS<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
{
const std::string cmd = Strings::format(R"("%s" --framework-version)", fs::u8string(path_to_exe));
- const auto rc = System::cmd_execute_and_capture_output(cmd);
+ auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code != 0)
{
- return nullopt;
+ return {Strings::concat(
+ std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
+ expected_right_tag};
}
/* Sample output:
3.1.81
*/
- return rc.output;
+ return {std::move(rc.output), expected_left_tag};
}
};
@@ -475,17 +510,19 @@ Mono JIT compiler version 6.8.0.105 (Debian 6.8.0.105+dfsg-2 Wed Feb 26 23:23:50
virtual const std::string& exe_stem() const override { return m_exe; }
virtual std::array<int, 3> default_min_version() const override { return {7, 0, 3}; }
- virtual Optional<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
+ virtual ExpectedS<std::string> get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override
{
- const auto pwsh_invocation = System::cmd_execute_and_capture_output(
+ auto rc = System::cmd_execute_and_capture_output(
System::CmdLineBuilder().path_arg(path_to_exe).string_arg("--version").extract());
- if (pwsh_invocation.exit_code != 0)
+ if (rc.exit_code != 0)
{
- return nullopt;
+ return {Strings::concat(
+ std::move(rc.output), "\n\nFailed to get version of ", fs::u8string(path_to_exe), "\n"),
+ expected_right_tag};
}
// Sample output: PowerShell 7.0.3\r\n
- auto output = std::move(pwsh_invocation.output);
+ auto output = std::move(rc.output);
if (!Strings::starts_with(output, "PowerShell "))
{
Checks::exit_with_message(
@@ -493,7 +530,7 @@ Mono JIT compiler version 6.8.0.105 (Debian 6.8.0.105+dfsg-2 Wed Feb 26 23:23:50
}
output.erase(0, 11);
- return Strings::trim(std::move(output));
+ return {Strings::trim(std::move(output)), expected_left_tag};
}
};