Runtime Error References | |||||
######################## | |||||
This page enumerates the possible errors that you may encounter while using | |||||
DDS, either from user error or environmental issues. | |||||
.. note:: | |||||
DDS will automatically emit links to the relevant error document when it | |||||
occurs. | |||||
Errors | |||||
****** | |||||
.. toctree:: | |||||
:maxdepth: 2 | |||||
:glob: | |||||
* |
Error: Invalid built-in toolchain | |||||
################################# | |||||
``dds`` requires a toolchain in order to build any packages or projects. It | |||||
ships with several built-in toolchains that do not require the user to write | |||||
any configuration files. | |||||
If you start your toolchain name (The `-t` or `--toolchain` argument) | |||||
with a leading colon, dds will interpret it as a reference to a built-in | |||||
toolchain. (Toolchain file paths cannot begin with a leading colon). | |||||
These toolchain names are encoded into the dds executable and cannot be | |||||
modified. | |||||
.. seealso:: | |||||
Refer to the documentation on :doc:`toolchains </guide/toolchains>` and | |||||
:ref:`toolchains.builtin`. |
Error: No such package in the catalog | |||||
##################################### | |||||
This error will occur when one attempts to obtain a package from the package | |||||
catalog by its specific ``name@version`` pair, but no such entry exists | |||||
in the catalog. | |||||
It is possible that the intended package *does exist* but that the spelling of | |||||
the package name or version number is incorrect. Firstly, check your spelling | |||||
and that the version number you have requested is correct. | |||||
In another case, it is possible that the package *exists somewhere*, but has | |||||
not been loaded into the local catalog. As of this writing, ``dds`` does not | |||||
automatically maintain the catalog against a central package repository, so | |||||
package entries must be loaded and imported manually. If you believe this to be | |||||
the case, refer to the section on the :doc:`/guide/catalog`, especially the | |||||
section :ref:`catalog.adding`. |
list the IDs of the packages, but none of the additional metadata about them. | list the IDs of the packages, but none of the additional metadata about them. | ||||
.. _catalog.adding: | |||||
Adding Packages to the Catalog | Adding Packages to the Catalog | ||||
****************************** | ****************************** | ||||
Alternatively, you can pass the name of a built-in toolchain. See below. | Alternatively, you can pass the name of a built-in toolchain. See below. | ||||
.. _toolchains.builtin: | |||||
Built-in Toolchains | Built-in Toolchains | ||||
******************* | ******************* | ||||
tut/index | tut/index | ||||
guide/index | guide/index | ||||
design | design | ||||
err/index | |||||
.. Hide the link to the error reference since we don't want it cluttering our | |||||
main toc, but we want Sphinx to not consider it "unreferenced." We'll generate | |||||
our own link | |||||
.. seealso:: | |||||
For in-depth error and troubleshooting information see: :doc:`err/index`. | |||||
Indices and tables | Indices and tables |
#include <dds/build/builder.hpp> | #include <dds/build/builder.hpp> | ||||
#include <dds/catalog/catalog.hpp> | #include <dds/catalog/catalog.hpp> | ||||
#include <dds/catalog/get.hpp> | #include <dds/catalog/get.hpp> | ||||
#include <dds/error/errors.hpp> | |||||
#include <dds/repo/repo.hpp> | #include <dds/repo/repo.hpp> | ||||
#include <dds/source/dist.hpp> | #include <dds/source/dist.hpp> | ||||
#include <dds/toolchain/from_dds.hpp> | #include <dds/toolchain/from_dds.hpp> | ||||
auto default_tc = tc_path.substr(1); | auto default_tc = tc_path.substr(1); | ||||
auto tc = dds::toolchain::get_builtin(default_tc); | auto tc = dds::toolchain::get_builtin(default_tc); | ||||
if (!tc.has_value()) { | if (!tc.has_value()) { | ||||
throw std::runtime_error( | |||||
fmt::format("Invalid default toolchain name '{}'", default_tc)); | |||||
dds::throw_user_error< | |||||
dds::errc::invalid_builtin_toolchain>("Invalid built-in toolchain name '{}'", | |||||
default_tc); | |||||
} | } | ||||
return std::move(*tc); | return std::move(*tc); | ||||
} else { | } else { | ||||
auto id = dds::package_id::parse(req); | auto id = dds::package_id::parse(req); | ||||
auto info = cat.get(id); | auto info = cat.get(id); | ||||
if (!info) { | if (!info) { | ||||
throw std::runtime_error( | |||||
fmt::format("No package in the catalog matched the ID '{}'", req)); | |||||
dds::throw_user_error<dds::errc::no_such_catalog_package>( | |||||
"No package in the catalog matched the ID '{}'", req); | |||||
} | } | ||||
auto tsd = dds::get_package_sdist(*info); | auto tsd = dds::get_package_sdist(*info); | ||||
auto out_path = out.Get(); | auto out_path = out.Get(); | ||||
} catch (const dds::user_cancelled&) { | } catch (const dds::user_cancelled&) { | ||||
spdlog::critical("Operation cancelled by user"); | spdlog::critical("Operation cancelled by user"); | ||||
return 2; | return 2; | ||||
} catch (const dds::user_error_base& e) { | |||||
spdlog::error("{}", e.what()); | |||||
spdlog::error("{}", e.explanation()); | |||||
spdlog::error("Refer: {}", e.error_reference()); | |||||
return 1; | |||||
} catch (const std::exception& e) { | } catch (const std::exception& e) { | ||||
spdlog::critical(e.what()); | spdlog::critical(e.what()); | ||||
return 2; | return 2; |
#include "./errors.hpp" | |||||
#include <cassert> | |||||
#include <stdexcept> | |||||
using namespace dds; | |||||
namespace { | |||||
std::string error_url_prefix = "http://localhost:3000/err/"; | |||||
std::string error_url_suffix(dds::errc ec) noexcept { | |||||
switch (ec) { | |||||
case errc::invalid_builtin_toolchain: | |||||
return "invalid-builtin-toolchain.html"; | |||||
case errc::no_such_catalog_package: | |||||
return "no-such-catalog-package.html"; | |||||
case errc::none: | |||||
break; | |||||
} | |||||
assert(false && "Unreachable code path generating error explanation URL"); | |||||
std::terminate(); | |||||
} | |||||
} // namespace | |||||
std::string dds::error_reference_of(dds::errc ec) noexcept { | |||||
return error_url_prefix + error_url_suffix(ec); | |||||
} | |||||
std::string_view dds::explanation_of(dds::errc ec) noexcept { | |||||
switch (ec) { | |||||
case errc::invalid_builtin_toolchain: | |||||
return R"( | |||||
If you start your toolchain name (The `-t` or `--toolchain` argument) | |||||
with a leading colon, dds will interpret it as a reference to a built-in | |||||
toolchain. (Toolchain file paths cannot begin with a leading colon). | |||||
These toolchain names are encoded into the dds executable and cannot be | |||||
modified. | |||||
)"; | |||||
case errc::no_such_catalog_package: | |||||
return R"( | |||||
The installation of a package was requested, but the given package ID was not | |||||
able to be found in the package catalog. Check the spelling and version number. | |||||
)"; | |||||
case errc::none: | |||||
break; | |||||
} | |||||
assert(false && "Unexpected execution path during error explanation. This is a DDS bug"); | |||||
std::terminate(); | |||||
} |
#pragma once | |||||
#include <spdlog/fmt/fmt.h> | |||||
#include <stdexcept> | |||||
#include <string_view> | |||||
namespace dds { | |||||
struct exception_base : std::runtime_error { | |||||
using runtime_error::runtime_error; | |||||
}; | |||||
struct user_error_base : exception_base { | |||||
using exception_base::exception_base; | |||||
virtual std::string error_reference() const noexcept = 0; | |||||
virtual std::string_view explanation() const noexcept = 0; | |||||
}; | |||||
enum class errc { | |||||
none = 0, | |||||
invalid_builtin_toolchain, | |||||
no_such_catalog_package, | |||||
}; | |||||
std::string error_reference_of(errc) noexcept; | |||||
std::string_view explanation_of(errc) noexcept; | |||||
template <errc ErrorCode> | |||||
struct user_error : user_error_base { | |||||
using user_error_base::user_error_base; | |||||
std::string error_reference() const noexcept override { return error_reference_of(ErrorCode); } | |||||
std::string_view explanation() const noexcept override { return explanation_of(ErrorCode); } | |||||
}; | |||||
using error_invalid_default_toolchain = user_error<errc::invalid_builtin_toolchain>; | |||||
template <errc ErrorCode, typename... Args> | |||||
[[noreturn]] void throw_user_error(std::string_view fmt_str, Args&&... args) { | |||||
throw user_error<ErrorCode>(fmt::format(fmt_str, std::forward<Args>(args)...)); | |||||
} | |||||
} // namespace dds |