mirror of https://github.com/mamba-org/mamba.git
Merge pull request #1563 from JohanMabille/expected
Plugged tl::expected and refactored MSubdirData construction
This commit is contained in:
commit
d07ee8abac
|
@ -283,6 +283,7 @@ macro(libmamba_create_target target_name linkage deps_linkage output_name)
|
|||
find_library(LIBSOLV_BUILD_STATICRARIES NAMES solv_static)
|
||||
find_library(LIBSOLVEXT_BUILD_STATICRARIES NAMES solvext_static)
|
||||
find_package(reproc++ CONFIG REQUIRED)
|
||||
find_package(tl-expected REQUIRED)
|
||||
|
||||
find_library(LIBXML2_LIBRARY NAMES libxml2)
|
||||
find_library(ICONV_LIBRARY NAMES libiconv)
|
||||
|
@ -308,6 +309,7 @@ macro(libmamba_create_target target_name linkage deps_linkage output_name)
|
|||
${sodium_LIBRARY_RELEASE}
|
||||
reproc++
|
||||
reproc
|
||||
tl::expected
|
||||
)
|
||||
|
||||
add_definitions("-DLIBARCHIVE_STATIC -DCURL_STATICLIB -DSOLV_BUILD_STATIC")
|
||||
|
@ -325,6 +327,7 @@ macro(libmamba_create_target target_name linkage deps_linkage output_name)
|
|||
find_package(OpenSSL REQUIRED)
|
||||
find_package(yaml-cpp CONFIG REQUIRED)
|
||||
find_package(reproc++ CONFIG REQUIRED)
|
||||
find_package(tl-expected REQUIRED)
|
||||
|
||||
set(LIBMAMBA_LIBRARIES_DEPS
|
||||
${LIBSOLV_LIBRARIES}
|
||||
|
@ -335,6 +338,7 @@ macro(libmamba_create_target target_name linkage deps_linkage output_name)
|
|||
${YAML_CPP_LIBRARIES}
|
||||
reproc++
|
||||
reproc
|
||||
tl::expected
|
||||
)
|
||||
|
||||
target_link_libraries(${target_name} PUBLIC
|
||||
|
|
|
@ -14,6 +14,7 @@ dependencies:
|
|||
- gtest
|
||||
- gmock
|
||||
- cpp-filesystem >=1.5.8
|
||||
- cpp-expected
|
||||
- reproc-cpp
|
||||
- yaml-cpp
|
||||
- termcolor-cpp
|
||||
|
|
|
@ -35,6 +35,12 @@ namespace mamba
|
|||
const std::string& filename);
|
||||
~DownloadTarget();
|
||||
|
||||
DownloadTarget(const DownloadTarget&) = delete;
|
||||
DownloadTarget& operator=(const DownloadTarget&) = delete;
|
||||
|
||||
DownloadTarget(DownloadTarget&&);
|
||||
DownloadTarget& operator=(DownloadTarget&&);
|
||||
|
||||
static size_t write_callback(char* ptr, size_t size, size_t nmemb, void* self);
|
||||
static size_t header_callback(char* buffer, size_t size, size_t nitems, void* self);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -280,7 +280,7 @@ namespace mamba
|
|||
const ProgressBar& progress_bar() const;
|
||||
|
||||
private:
|
||||
ProgressBar* p_progress_bar;
|
||||
ProgressBar* p_progress_bar = nullptr;
|
||||
std::size_t m_width = 0;
|
||||
|
||||
void set_same_widths(const ProgressBarRepr& r);
|
||||
|
@ -359,7 +359,7 @@ namespace mamba
|
|||
int width() const;
|
||||
|
||||
private:
|
||||
ProgressBar* p_bar;
|
||||
ProgressBar* p_bar = nullptr;
|
||||
|
||||
friend class ProgressBarManager;
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
#include "tl/expected.hpp"
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
#include "mamba/core/channel.hpp"
|
||||
|
@ -31,6 +32,13 @@ namespace decompress
|
|||
|
||||
namespace mamba
|
||||
{
|
||||
|
||||
enum class subdirdata_error
|
||||
{
|
||||
unknown,
|
||||
load
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a channel subdirectory (i.e. a platform)
|
||||
* packages index. Handles downloading of the index
|
||||
|
@ -39,11 +47,22 @@ namespace mamba
|
|||
class MSubdirData
|
||||
{
|
||||
public:
|
||||
MSubdirData(const Channel& channel,
|
||||
const std::string& platform,
|
||||
const std::string& url,
|
||||
MultiPackageCache& caches,
|
||||
const std::string& repodata_fn = "repodata.json");
|
||||
template <class T>
|
||||
using expected = tl::expected<T, mamba_error<subdirdata_error>>;
|
||||
|
||||
static expected<MSubdirData> create(const Channel& channel,
|
||||
const std::string& platform,
|
||||
const std::string& url,
|
||||
MultiPackageCache& caches,
|
||||
const std::string& repodata_fn = "repodata.json");
|
||||
|
||||
~MSubdirData() = default;
|
||||
|
||||
MSubdirData(const MSubdirData&) = delete;
|
||||
MSubdirData& operator=(const MSubdirData&) = delete;
|
||||
|
||||
MSubdirData(MSubdirData&&);
|
||||
MSubdirData& operator=(MSubdirData&&);
|
||||
|
||||
// TODO return seconds as double
|
||||
fs::file_time_type::duration check_cache(const fs::path& cache_file,
|
||||
|
@ -62,19 +81,24 @@ namespace mamba
|
|||
MRepo& create_repo(MPool& pool);
|
||||
|
||||
private:
|
||||
MSubdirData(const Channel& channel,
|
||||
const std::string& platform,
|
||||
const std::string& url,
|
||||
MultiPackageCache& caches,
|
||||
const std::string& repodata_fn = "repodata.json");
|
||||
|
||||
bool load();
|
||||
bool decompress();
|
||||
void create_target(nlohmann::json& mod_etag);
|
||||
std::size_t get_cache_control_max_age(const std::string& val);
|
||||
|
||||
std::unique_ptr<DownloadTarget> m_target;
|
||||
std::unique_ptr<DownloadTarget> m_target = nullptr;
|
||||
|
||||
bool m_json_cache_valid = false;
|
||||
bool m_solv_cache_valid = false;
|
||||
|
||||
fs::path m_valid_cache_path, m_expired_cache_path;
|
||||
|
||||
std::ofstream out_file;
|
||||
fs::path m_valid_cache_path;
|
||||
fs::path m_expired_cache_path;
|
||||
|
||||
ProgressProxy m_progress_bar;
|
||||
|
||||
|
@ -84,7 +108,7 @@ namespace mamba
|
|||
std::string m_name;
|
||||
std::string m_json_fn;
|
||||
std::string m_solv_fn;
|
||||
MultiPackageCache& m_caches;
|
||||
MultiPackageCache* p_caches;
|
||||
bool m_is_noarch;
|
||||
nlohmann::json m_mod_etag;
|
||||
std::unique_ptr<TemporaryFile> m_temp_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
|
||||
|
|
|
@ -24,6 +24,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR};${CMAKE_MODULE_PATH}")
|
|||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(nlohmann_json)
|
||||
find_dependency(Threads)
|
||||
find_dependency(tl-expected)
|
||||
|
||||
if(NOT (TARGET libmamba OR TARGET libmamba-static OR TARGET libmamba-full-static))
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
|
|
|
@ -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";
|
||||
|
@ -38,7 +44,7 @@ namespace mamba
|
|||
|
||||
std::vector<std::string> channel_urls = ctx.channels;
|
||||
|
||||
std::vector<std::shared_ptr<MSubdirData>> subdirs;
|
||||
std::vector<MSubdirData> subdirs;
|
||||
MultiDownloadTarget multi_dl;
|
||||
|
||||
std::vector<std::pair<int, int>> priorities;
|
||||
|
@ -53,10 +59,18 @@ namespace mamba
|
|||
{
|
||||
for (auto& [platform, url] : channel->platform_urls(true))
|
||||
{
|
||||
auto sdir = std::make_shared<MSubdirData>(*channel, platform, url, package_caches);
|
||||
auto sdires = MSubdirData::create(*channel, platform, url, package_caches);
|
||||
if (!sdires.has_value())
|
||||
{
|
||||
// TODO: error handling
|
||||
continue;
|
||||
}
|
||||
// auto sdir = std::make_shared<MSubdirData>(*channel, platform, url,
|
||||
// package_caches);
|
||||
auto sdir = std::move(sdires).value();
|
||||
|
||||
multi_dl.add(sdir->target());
|
||||
subdirs.push_back(sdir);
|
||||
multi_dl.add(sdir.target());
|
||||
subdirs.push_back(std::move(sdir));
|
||||
if (ctx.channel_priority == ChannelPriority::kDisabled)
|
||||
{
|
||||
priorities.push_back(std::make_pair(0, 0));
|
||||
|
@ -90,22 +104,22 @@ namespace mamba
|
|||
for (std::size_t i = 0; i < subdirs.size(); ++i)
|
||||
{
|
||||
auto& subdir = subdirs[i];
|
||||
if (!subdir->loaded())
|
||||
if (!subdir.loaded())
|
||||
{
|
||||
if (ctx.offline || !mamba::ends_with(subdir->name(), "/noarch"))
|
||||
if (ctx.offline || !mamba::ends_with(subdir.name(), "/noarch"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Subdir " + subdir->name() + " not loaded!");
|
||||
throw std::runtime_error("Subdir " + subdir.name() + " not loaded!");
|
||||
}
|
||||
}
|
||||
|
||||
auto& prio = priorities[i];
|
||||
try
|
||||
{
|
||||
MRepo& repo = subdir->create_repo(pool);
|
||||
MRepo& repo = subdir.create_repo(pool);
|
||||
repo.set_priority(prio.first, prio.second);
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
|
@ -113,14 +127,14 @@ namespace mamba
|
|||
if (is_retry & RETRY_SUBDIR_FETCH)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Could not load repodata.json for " << subdir->name() << " after retry."
|
||||
ss << "Could not load repodata.json for " << subdir.name() << " after retry."
|
||||
<< "Please check repodata source. Exiting." << std::endl;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
LOG_WARNING << "Could not load repodata.json for " << subdir->name()
|
||||
LOG_WARNING << "Could not load repodata.json for " << subdir.name()
|
||||
<< ". Deleting cache, and retrying.";
|
||||
subdir->clear_cache();
|
||||
subdir.clear_cache();
|
||||
loading_failed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 });
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -152,6 +152,72 @@ namespace mamba
|
|||
init_curl_target(m_url);
|
||||
}
|
||||
|
||||
DownloadTarget::~DownloadTarget()
|
||||
{
|
||||
curl_easy_cleanup(m_handle);
|
||||
curl_slist_free_all(m_headers);
|
||||
}
|
||||
|
||||
DownloadTarget::DownloadTarget(DownloadTarget&& rhs)
|
||||
: result(std::move(rhs.result))
|
||||
, failed(std::move(rhs.failed))
|
||||
, http_status(std::move(rhs.http_status))
|
||||
, downloaded_size(std::move(rhs.downloaded_size))
|
||||
, avg_speed(std::move(rhs.avg_speed))
|
||||
, final_url(std::move(rhs.final_url))
|
||||
, etag(std::move(rhs.etag))
|
||||
, mod(std::move(rhs.mod))
|
||||
, cache_control(std::move(rhs.cache_control))
|
||||
, m_finalize_callback(std::move(rhs.m_finalize_callback))
|
||||
, m_name(std::move(rhs.m_name))
|
||||
, m_filename(std::move(rhs.m_filename))
|
||||
, m_url(std::move(rhs.m_url))
|
||||
, m_expected_size(std::move(rhs.m_expected_size))
|
||||
, m_next_retry(std::move(rhs.m_next_retry))
|
||||
, m_retry_wait_seconds(std::move(rhs.m_retry_wait_seconds))
|
||||
, m_retries(std::move(rhs.m_retries))
|
||||
, m_handle(std::move(rhs.m_handle))
|
||||
, m_headers(std::move(rhs.m_headers))
|
||||
, m_has_progress_bar(std::move(rhs.m_has_progress_bar))
|
||||
, m_ignore_failure(std::move(rhs.m_ignore_failure))
|
||||
, m_progress_bar(std::move(rhs.m_progress_bar))
|
||||
, m_file(std::move(rhs.m_file))
|
||||
{
|
||||
rhs.m_handle = nullptr;
|
||||
rhs.m_headers = nullptr;
|
||||
std::copy(rhs.m_errbuf, rhs.m_errbuf + CURL_ERROR_SIZE, m_errbuf);
|
||||
}
|
||||
|
||||
DownloadTarget& DownloadTarget::operator=(DownloadTarget&& rhs)
|
||||
{
|
||||
using std::swap;
|
||||
swap(result, rhs.result);
|
||||
swap(failed, rhs.failed);
|
||||
swap(http_status, rhs.http_status);
|
||||
swap(downloaded_size, rhs.downloaded_size);
|
||||
swap(avg_speed, rhs.avg_speed);
|
||||
swap(final_url, rhs.final_url);
|
||||
swap(etag, rhs.etag);
|
||||
swap(mod, rhs.mod);
|
||||
swap(cache_control, rhs.cache_control);
|
||||
swap(m_finalize_callback, m_finalize_callback);
|
||||
swap(m_name, rhs.m_name);
|
||||
swap(m_filename, rhs.m_filename);
|
||||
swap(m_url, rhs.m_url);
|
||||
swap(m_expected_size, rhs.m_expected_size);
|
||||
swap(m_next_retry, rhs.m_next_retry);
|
||||
swap(m_retry_wait_seconds, rhs.m_retry_wait_seconds);
|
||||
swap(m_retries, rhs.m_retries);
|
||||
swap(m_handle, rhs.m_handle);
|
||||
swap(m_headers, rhs.m_headers);
|
||||
swap(m_has_progress_bar, rhs.m_has_progress_bar);
|
||||
swap(m_ignore_failure, rhs.m_ignore_failure);
|
||||
swap(m_progress_bar, rhs.m_progress_bar);
|
||||
swap(m_errbuf, rhs.m_errbuf);
|
||||
swap(m_file, rhs.m_file);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void DownloadTarget::init_curl_handle(CURL* handle, const std::string& url)
|
||||
{
|
||||
curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
|
||||
|
@ -237,7 +303,6 @@ namespace mamba
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void DownloadTarget::init_curl_target(const std::string& url)
|
||||
{
|
||||
init_curl_handle(m_handle, url);
|
||||
|
@ -307,11 +372,6 @@ namespace mamba
|
|||
}
|
||||
}
|
||||
|
||||
DownloadTarget::~DownloadTarget()
|
||||
{
|
||||
curl_easy_cleanup(m_handle);
|
||||
curl_slist_free_all(m_headers);
|
||||
}
|
||||
|
||||
size_t DownloadTarget::write_callback(char* ptr, size_t size, size_t nmemb, void* self)
|
||||
{
|
||||
|
@ -613,7 +673,9 @@ namespace mamba
|
|||
|
||||
bool ret = true;
|
||||
if (m_finalize_callback)
|
||||
{
|
||||
ret = m_finalize_callback();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_has_progress_bar)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -160,17 +160,39 @@ namespace mamba
|
|||
|
||||
}
|
||||
|
||||
auto MSubdirData::create(const Channel& channel,
|
||||
const std::string& platform,
|
||||
const std::string& url,
|
||||
MultiPackageCache& caches,
|
||||
const std::string& repodata_fn) -> expected<MSubdirData>
|
||||
{
|
||||
try
|
||||
{
|
||||
return MSubdirData(channel, platform, url, caches, repodata_fn);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
return tl::make_unexpected(mamba_error(e.what(), subdirdata_error::load));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return tl::make_unexpected(mamba_error(
|
||||
"Unkown error when trying to load subdir data " + url, subdirdata_error::unknown));
|
||||
}
|
||||
}
|
||||
|
||||
MSubdirData::MSubdirData(const Channel& channel,
|
||||
const std::string& platform,
|
||||
const std::string& url,
|
||||
MultiPackageCache& caches,
|
||||
const std::string& repodata_fn)
|
||||
: m_progress_bar(ProgressProxy())
|
||||
: m_target(nullptr)
|
||||
, m_progress_bar()
|
||||
, m_loaded(false)
|
||||
, m_download_complete(false)
|
||||
, m_repodata_url(concat(url, "/", repodata_fn))
|
||||
, m_name(concat(channel.canonical_name(), "/", platform))
|
||||
, m_caches(caches)
|
||||
, p_caches(&caches)
|
||||
, m_is_noarch(platform == "noarch")
|
||||
, p_channel(&channel)
|
||||
{
|
||||
|
@ -179,6 +201,63 @@ namespace mamba
|
|||
load();
|
||||
}
|
||||
|
||||
MSubdirData::MSubdirData(MSubdirData&& rhs)
|
||||
: m_target(std::move(rhs.m_target))
|
||||
, m_json_cache_valid(rhs.m_json_cache_valid)
|
||||
, m_solv_cache_valid(rhs.m_solv_cache_valid)
|
||||
, m_valid_cache_path(std::move(rhs.m_valid_cache_path))
|
||||
, m_expired_cache_path(std::move(rhs.m_expired_cache_path))
|
||||
, m_progress_bar(std::move(rhs.m_progress_bar))
|
||||
, m_loaded(rhs.m_loaded)
|
||||
, m_download_complete(rhs.m_download_complete)
|
||||
, m_repodata_url(std::move(rhs.m_repodata_url))
|
||||
, m_name(std::move(rhs.m_name))
|
||||
, m_json_fn(std::move(rhs.m_json_fn))
|
||||
, m_solv_fn(std::move(rhs.m_solv_fn))
|
||||
, p_caches(rhs.p_caches)
|
||||
, m_is_noarch(rhs.m_is_noarch)
|
||||
, m_mod_etag(std::move(rhs.m_mod_etag))
|
||||
, m_temp_file(std::move(rhs.m_temp_file))
|
||||
, p_channel(rhs.p_channel)
|
||||
{
|
||||
if (m_target != nullptr)
|
||||
{
|
||||
m_target->set_finalize_callback(&MSubdirData::finalize_transfer, this);
|
||||
}
|
||||
}
|
||||
|
||||
MSubdirData& MSubdirData::operator=(MSubdirData&& rhs)
|
||||
{
|
||||
using std::swap;
|
||||
swap(m_target, rhs.m_target);
|
||||
swap(m_json_cache_valid, rhs.m_json_cache_valid);
|
||||
swap(m_solv_cache_valid, rhs.m_solv_cache_valid);
|
||||
swap(m_valid_cache_path, rhs.m_valid_cache_path);
|
||||
swap(m_expired_cache_path, rhs.m_expired_cache_path);
|
||||
swap(m_progress_bar, m_progress_bar);
|
||||
swap(m_loaded, rhs.m_loaded);
|
||||
swap(m_download_complete, rhs.m_download_complete);
|
||||
swap(m_repodata_url, rhs.m_repodata_url);
|
||||
swap(m_name, rhs.m_name);
|
||||
swap(m_json_fn, rhs.m_json_fn);
|
||||
swap(m_solv_fn, rhs.m_solv_fn);
|
||||
swap(p_caches, rhs.p_caches);
|
||||
swap(m_is_noarch, rhs.m_is_noarch);
|
||||
swap(m_mod_etag, rhs.m_mod_etag);
|
||||
swap(m_temp_file, rhs.m_temp_file);
|
||||
swap(p_channel, rhs.p_channel);
|
||||
|
||||
if (m_target != nullptr)
|
||||
{
|
||||
m_target->set_finalize_callback(&MSubdirData::finalize_transfer, this);
|
||||
}
|
||||
if (rhs.m_target != nullptr)
|
||||
{
|
||||
rhs.m_target->set_finalize_callback(&MSubdirData::finalize_transfer, &rhs);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
fs::file_time_type::duration MSubdirData::check_cache(
|
||||
const fs::path& cache_file, const fs::file_time_type::clock::time_point& ref)
|
||||
{
|
||||
|
@ -216,7 +295,7 @@ namespace mamba
|
|||
|
||||
LOG_INFO << "Searching index cache file for repo '" << m_repodata_url << "'";
|
||||
|
||||
for (const auto& cache_path : m_caches.paths())
|
||||
for (const auto& cache_path : p_caches->paths())
|
||||
{
|
||||
auto json_file = cache_path / "cache" / m_json_fn;
|
||||
auto solv_file = cache_path / "cache" / m_solv_fn;
|
||||
|
@ -366,7 +445,7 @@ namespace mamba
|
|||
}
|
||||
|
||||
fs::path json_file, solv_file;
|
||||
fs::path writable_cache_path = m_caches.first_writable_path();
|
||||
fs::path writable_cache_path = p_caches->first_writable_path();
|
||||
|
||||
if (m_target->http_status == 304)
|
||||
{
|
||||
|
|
|
@ -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" };
|
||||
|
|
|
@ -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(c, "linux-64", "file:///nonexistent/repodata.json", pkg_cache);
|
||||
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(c, "noarch", "file:///nonexistent/repodata.json", pkg_cache);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ dependencies:
|
|||
- gtest
|
||||
- gmock
|
||||
- cpp-filesystem >=1.5.8
|
||||
- cpp-expected
|
||||
- reproc-cpp
|
||||
- yaml-cpp
|
||||
- termcolor-cpp
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
@ -236,12 +236,26 @@ 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&,
|
||||
const std::string&,
|
||||
const std::string&,
|
||||
MultiPackageCache&,
|
||||
const std::string&>())
|
||||
.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())
|
||||
{
|
||||
return std::move(sres.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw sres.error();
|
||||
}
|
||||
}))
|
||||
.def("create_repo", &MSubdirData::create_repo, py::return_value_policy::reference)
|
||||
.def("loaded", &MSubdirData::loaded)
|
||||
.def("cache_path", &MSubdirData::cache_path);
|
||||
|
@ -306,7 +320,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);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ dependencies:
|
|||
- gtest
|
||||
- gmock
|
||||
- cpp-filesystem >=1.5.8
|
||||
- cpp-expected
|
||||
- reproc-cpp
|
||||
- yaml-cpp
|
||||
- termcolor-cpp
|
||||
|
|
|
@ -14,6 +14,7 @@ dependencies:
|
|||
- gtest
|
||||
- gmock
|
||||
- cpp-filesystem >=1.5.8
|
||||
- cpp-expected
|
||||
- reproc-cpp
|
||||
- yaml-cpp
|
||||
- termcolor-cpp
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue