added static create method to PrefixData + error handling

This commit is contained in:
Johan Mabille 2022-03-10 18:07:07 +01:00
parent 3f6bfb59bf
commit d5da2b3bf9
17 changed files with 185 additions and 63 deletions

View File

@ -9,6 +9,7 @@
#include <string>
#include <unordered_map>
#include "tl/expected.hpp"
#include "history.hpp"
#include "package_info.hpp"
@ -16,12 +17,21 @@
namespace mamba
{
enum class prefixdata_error
{
unknown,
load
};
class PrefixData
{
public:
using package_map = std::unordered_map<std::string, PackageInfo>;
PrefixData(const fs::path& prefix_path);
template <class T>
using expected = tl::expected<T, mamba_error<prefixdata_error>>;
static expected<PrefixData> create(const fs::path& prefix_path);
void add_packages(const std::vector<PackageInfo>& packages);
const package_map& records() const;
@ -32,6 +42,7 @@ namespace mamba
std::vector<PackageInfo> sorted_records() const;
private:
PrefixData(const fs::path& prefix_path);
void load();
History m_history;

View File

@ -33,17 +33,10 @@ namespace decompress
namespace mamba
{
class subdirdata_error
enum class subdirdata_error
{
public:
subdirdata_error(const char* msg);
subdirdata_error(const std::string& msg);
const std::string& what() const noexcept;
private:
std::string m_message;
unknown,
load
};
/**
@ -55,7 +48,7 @@ namespace mamba
{
public:
template <class T>
using expected = tl::expected<T, subdirdata_error>;
using expected = tl::expected<T, mamba_error<subdirdata_error>>;
static expected<MSubdirData> create(const Channel& channel,
const std::string& platform,

View File

@ -52,12 +52,6 @@ namespace mamba
const static std::regex token_re("/t/([a-zA-Z0-9-_]{0,2}[a-zA-Z0-9-]*)");
const static std::regex http_basicauth_re("://([^\\s]+):([^\\s]+)@");
class mamba_error : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};
bool is_package_file(const std::string_view& fn);
bool lexists(const fs::path& p);
@ -117,6 +111,26 @@ namespace mamba
return result;
}
enum class unspecified_error
{
unkown
};
template <class error_type>
class mamba_error : public std::runtime_error
{
public:
using base_type = std::runtime_error;
mamba_error(const std::string& msg, error_type ec);
mamba_error(const char* msg, error_type ec);
error_type error_code() const noexcept;
private:
error_type m_error_code;
};
class TemporaryDirectory
{
public:
@ -467,6 +481,30 @@ namespace mamba
std::tuple<std::vector<std::string>, std::unique_ptr<TemporaryFile>> prepare_wrapped_call(
const fs::path& prefix, const std::vector<std::string>& cmd);
/******************************
* mamba_error implementation *
******************************/
template <class ET>
mamba_error<ET>::mamba_error(const std::string& msg, ET ec)
: base_type(msg)
, m_error_code(ec)
{
}
template <class ET>
mamba_error<ET>::mamba_error(const char* msg, ET ec)
: base_type(msg)
, m_error_code(ec)
{
}
template <class ET>
ET mamba_error<ET>::error_code() const noexcept
{
return m_error_code;
}
} // namespace mamba
#endif // MAMBA_UTIL_HPP

View File

@ -14,9 +14,15 @@ namespace mamba
{
if (!fs::exists(pkgs_dir))
{
// TODO : us tl::expected mechanis
throw std::runtime_error("Specified pkgs_dir does not exist\n");
}
PrefixData prefix_data(pkgs_dir);
auto sprefix_data = PrefixData::create(pkgs_dir);
if (!sprefix_data)
{
throw std::runtime_error("Specified pkgs_dir does not exist\n");
}
PrefixData& prefix_data = sprefix_data.value();
for (const auto& entry : fs::directory_iterator(pkgs_dir))
{
fs::path repodata_record_json = entry.path() / "info" / "repodata_record.json";
@ -59,7 +65,8 @@ namespace mamba
// TODO: error handling
continue;
}
//auto sdir = std::make_shared<MSubdirData>(*channel, platform, url, package_caches);
// auto sdir = std::make_shared<MSubdirData>(*channel, platform, url,
// package_caches);
auto sdir = std::move(sdires).value();
multi_dl.add(sdir.target());

View File

@ -358,8 +358,13 @@ namespace mamba
MPool pool;
load_channels(pool, package_caches, is_retry);
PrefixData prefix_data(ctx.target_prefix);
auto sprefix_data = PrefixData::create(ctx.target_prefix);
if (!sprefix_data)
{
// TODO: propagate tl::expected mechanism
throw std::runtime_error("could not load prefix data");
}
PrefixData& prefix_data = sprefix_data.value();
std::vector<std::string> prefix_pkgs;
for (auto& it : prefix_data.records())
@ -463,7 +468,14 @@ namespace mamba
{
MPool pool;
auto& ctx = Context::instance();
PrefixData prefix_data(ctx.target_prefix);
auto sprefix_data = PrefixData::create(ctx.target_prefix);
if (!sprefix_data)
{
// TODO: propagate tl::expected mechanism
throw std::runtime_error("could not load prefix data");
}
PrefixData& prefix_data = sprefix_data.value();
fs::path pkgs_dirs(Context::instance().root_prefix / "pkgs");
MultiPackageCache pkg_caches({ pkgs_dirs });

View File

@ -46,7 +46,13 @@ namespace mamba
{
auto& ctx = Context::instance();
PrefixData prefix_data(ctx.target_prefix);
auto sprefix_data = PrefixData::create(ctx.target_prefix);
if (!sprefix_data)
{
// TODO: propagate tl::expected mechanism
throw std::runtime_error("could not load prefix data");
}
PrefixData& prefix_data = sprefix_data.value();
std::regex spec_pat(regex);

View File

@ -35,8 +35,13 @@ namespace mamba
if (remove_all)
{
PrefixData prefix_data(ctx.target_prefix);
auto sprefix_data = PrefixData::create(ctx.target_prefix);
if (!sprefix_data)
{
// TODO: propagate tl::expected mechanism
throw std::runtime_error("could not load prefix data");
}
PrefixData& prefix_data = sprefix_data.value();
for (const auto& package : prefix_data.records())
{
remove_specs.push_back(package.second.name);
@ -67,7 +72,13 @@ namespace mamba
throw std::runtime_error("Aborted.");
}
PrefixData prefix_data(ctx.target_prefix);
auto sprefix_data = PrefixData::create(ctx.target_prefix);
if (!sprefix_data)
{
// TODO: propagate tl::expected mechanism
throw std::runtime_error("could not load prefix data");
}
PrefixData& prefix_data = sprefix_data.value();
MPool pool;
MRepo::create(pool, prefix_data);

View File

@ -29,7 +29,13 @@ namespace mamba
MultiPackageCache package_caches(ctx.pkgs_dirs);
if (use_local)
{
auto prefix_data = PrefixData(ctx.target_prefix);
auto sprefix_data = PrefixData::create(ctx.target_prefix);
if (!sprefix_data)
{
// TODO: propagate tl::expected mechanism
throw std::runtime_error("could not load prefix data");
}
PrefixData& prefix_data = sprefix_data.value();
MRepo::create(pool, prefix_data);
Console::stream() << "Loaded current active prefix: " << ctx.target_prefix << std::endl;
}

View File

@ -37,7 +37,13 @@ namespace mamba
load_channels(pool, package_caches, 0);
PrefixData prefix_data(ctx.target_prefix);
auto sprefix_data = PrefixData::create(ctx.target_prefix);
if (!sprefix_data)
{
// TODO: propagate tl::expected mechanism
throw std::runtime_error("could not load prefix data");
}
PrefixData& prefix_data = sprefix_data.value();
std::vector<std::string> prefix_pkgs;
for (auto& it : prefix_data.records())

View File

@ -185,7 +185,7 @@ namespace mamba
{
rhs.m_handle = nullptr;
rhs.m_headers = nullptr;
std::copy(rhs.m_errbuf, rhs.m_errbuf+CURL_ERROR_SIZE, m_errbuf);
std::copy(rhs.m_errbuf, rhs.m_errbuf + CURL_ERROR_SIZE, m_errbuf);
}
DownloadTarget& DownloadTarget::operator=(DownloadTarget&& rhs)

View File

@ -14,6 +14,24 @@
namespace mamba
{
auto PrefixData::create(const fs::path& prefix_path) -> expected<PrefixData>
{
try
{
return PrefixData(prefix_path);
}
catch (std::exception& e)
{
return tl::make_unexpected(mamba_error(e.what(), prefixdata_error::load));
}
catch (...)
{
return tl::make_unexpected(mamba_error("Unkown error when trying to load prefix data "
+ std::string(prefix_path),
prefixdata_error::unknown));
}
}
PrefixData::PrefixData(const fs::path& prefix_path)
: m_history(prefix_path)
, m_prefix_path(prefix_path)

View File

@ -707,7 +707,7 @@ namespace mamba
: p_bar(ptr)
{
}
bool ProgressProxy::defined() const
{
return p_bar != nullptr;

View File

@ -160,21 +160,6 @@ namespace mamba
}
subdirdata_error::subdirdata_error(const char* msg)
: m_message(msg)
{
}
subdirdata_error::subdirdata_error(const std::string& msg)
: m_message(msg)
{
}
const std::string& subdirdata_error::what() const noexcept
{
return m_message;
}
auto MSubdirData::create(const Channel& channel,
const std::string& platform,
const std::string& url,
@ -185,13 +170,14 @@ namespace mamba
{
return MSubdirData(channel, platform, url, caches, repodata_fn);
}
catch(std::exception& e)
catch (std::exception& e)
{
return tl::make_unexpected(e.what());
return tl::make_unexpected(mamba_error(e.what(), subdirdata_error::load));
}
catch(...)
catch (...)
{
return tl::make_unexpected("Unkown error when trying to load subdir data " + url);
return tl::make_unexpected(mamba_error(
"Unkown error when trying to load subdir data " + url, subdirdata_error::unknown));
}
}

View File

@ -11,7 +11,14 @@ namespace mamba
{
std::vector<std::string> specs;
std::string pin;
PrefixData prefix_data("");
auto sprefix_data = PrefixData::create("");
if (!sprefix_data)
{
// TODO: propagate tl::expected mechanism
throw std::runtime_error("could not load prefix data");
}
PrefixData& prefix_data = sprefix_data.value();
ASSERT_EQ(prefix_data.records().size(), 0);
specs = { "python" };

View File

@ -13,7 +13,10 @@ namespace mamba
const mamba::Channel& c = mamba::make_channel("conda-forge");
mamba::MultiDownloadTarget multi_dl;
mamba::MultiPackageCache pkg_cache({ "/tmp/" });
mamba::MSubdirData cf = mamba::MSubdirData::create(c, "linux-64", "file:///nonexistent/repodata.json", pkg_cache).value();
mamba::MSubdirData cf
= mamba::MSubdirData::create(
c, "linux-64", "file:///nonexistent/repodata.json", pkg_cache)
.value();
multi_dl.add(cf.target());
// file:// url should not retry
@ -28,7 +31,9 @@ namespace mamba
const mamba::Channel& c = mamba::make_channel("conda-forge");
mamba::MultiDownloadTarget multi_dl;
mamba::MultiPackageCache pkg_cache({ "/tmp/" });
mamba::MSubdirData cf = mamba::MSubdirData::create(c, "noarch", "file:///nonexistent/repodata.json", pkg_cache).value();
mamba::MSubdirData cf = mamba::MSubdirData::create(
c, "noarch", "file:///nonexistent/repodata.json", pkg_cache)
.value();
multi_dl.add(cf.target());
EXPECT_THROW(multi_dl.download(MAMBA_DOWNLOAD_FAILFAST), std::runtime_error);
}

View File

@ -57,7 +57,7 @@ PYBIND11_MODULE(bindings, m)
py::class_<mamba::LockFile>(m, "LockFile").def(py::init<fs::path>());
py::register_exception<mamba_error>(m, "MambaNativeException");
py::register_exception<mamba_error<unspecified_error>>(m, "MambaNativeException");
py::add_ostream_redirect(m, "ostream_redirect");
@ -225,12 +225,15 @@ PYBIND11_MODULE(bindings, m)
return res_stream.str();
});
py::register_exception<mamba_error<subdirdata_error>>(m, "SubdirDataError");
py::class_<MSubdirData>(m, "SubdirData")
.def(py::init([](const Channel& channel,
const std::string& platform,
const std::string& url,
MultiPackageCache& caches,
const std::string& repodata_fn) -> MSubdirData
.def(py::init(
[](const Channel& channel,
const std::string& platform,
const std::string& url,
MultiPackageCache& caches,
const std::string& repodata_fn) -> MSubdirData
{
auto sres = MSubdirData::create(channel, platform, url, caches, repodata_fn);
if (sres.has_value())
@ -239,7 +242,7 @@ PYBIND11_MODULE(bindings, m)
}
else
{
throw std::runtime_error(sres.error().what());
throw sres.error();
}
}))
.def("create_repo", &MSubdirData::create_repo, py::return_value_policy::reference)
@ -306,7 +309,19 @@ PYBIND11_MODULE(bindings, m)
.def("set_log_level", &Context::set_log_level);
py::class_<PrefixData>(m, "PrefixData")
.def(py::init<const fs::path&>())
.def(py::init(
[](const fs::path& prefix_path) -> PrefixData
{
auto sres = PrefixData::create(prefix_path);
if (sres.has_value())
{
return std::move(sres.value());
}
else
{
throw sres.error();
}
}))
.def_property_readonly("package_records", &PrefixData::records)
.def("add_packages", &PrefixData::add_packages);

View File

@ -66,7 +66,8 @@ set_env_command(CLI::App* com)
if (explicit_format)
{
PrefixData pd(ctx.target_prefix);
// TODO: handle error
auto pd = PrefixData::create(ctx.target_prefix).value();
auto records = pd.sorted_records();
std::cout << "# This file may be used to create an environment using:\n"
<< "# $ conda create --name <env> --file <this file>\n"
@ -87,7 +88,7 @@ set_env_command(CLI::App* com)
}
else
{
PrefixData pd(ctx.target_prefix);
auto pd = PrefixData::create(ctx.target_prefix).value();
History& hist = pd.history();
auto versions_map = pd.records();