Add cpp linter and fix warnings

This commit is contained in:
Marcelo Trevisani 2020-08-03 13:30:13 +01:00
parent ffcd4a8f63
commit 98f2530d23
73 changed files with 11426 additions and 10123 deletions

52
.clang-format Normal file
View File

@ -0,0 +1,52 @@
BasedOnStyle: Mozilla
AccessModifierOffset: '-4'
AlignAfterOpenBracket: Align
AlignEscapedNewlinesLeft: 'false'
AllowAllParametersOfDeclarationOnNextLine: 'true'
AllowShortBlocksOnASingleLine: 'false'
AllowShortCaseLabelsOnASingleLine: 'false'
AllowShortFunctionsOnASingleLine: 'false'
AllowShortIfStatementsOnASingleLine: 'false'
AllowShortLoopsOnASingleLine: 'false'
AlwaysBreakTemplateDeclarations: 'true'
SpaceAfterTemplateKeyword: 'true'
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Allman
BreakBeforeTernaryOperators: 'true'
BreakConstructorInitializersBeforeComma: 'true'
BreakStringLiterals: 'false'
ColumnLimit: '100'
ConstructorInitializerAllOnOneLineOrOnePerLine: 'false'
ConstructorInitializerIndentWidth: '4'
ContinuationIndentWidth: '4'
Cpp11BracedListStyle: 'false'
DerivePointerAlignment: 'false'
DisableFormat: 'false'
ExperimentalAutoDetectBinPacking: 'true'
IndentCaseLabels: 'true'
IndentWidth: '4'
IndentWrappedFunctionNames: 'false'
JavaScriptQuotes: Single
KeepEmptyLinesAtTheStartOfBlocks: 'false'
Language: Cpp
MaxEmptyLinesToKeep: '2'
NamespaceIndentation: All
ObjCBlockIndentWidth: '4'
ObjCSpaceAfterProperty: 'false'
ObjCSpaceBeforeProtocolList: 'false'
PointerAlignment: Left
ReflowComments: 'true'
SortIncludes: 'false'
SpaceAfterCStyleCast: 'true'
SpaceBeforeAssignmentOperators: 'true'
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: 'false'
SpacesBeforeTrailingComments: '2'
SpacesInAngles: 'false'
SpacesInCStyleCastParentheses: 'false'
SpacesInContainerLiterals: 'false'
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
Standard: Cpp11
TabWidth: '4'
UseTab: Never

View File

@ -1,4 +1,4 @@
name: linter
name: Linters (Python, C++)
on:
push:
@ -17,11 +17,28 @@ jobs:
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Setup Miniconda
uses: goanpeca/setup-miniconda@v1.0.2
with:
miniconda-version: 'latest'
activate-environment: linters
python-version: 3.8
auto-update-conda: true
- name: Config Channels
shell: pwsh
run: |
conda config --set always_yes yes
conda config --add channels conda-forge
- name: Install dependencies
shell: pwsh
run: |
python -m pip install pre-commit
conda install clang clang-tools=10.0.1 pre-commit
- name: Conda info
shell: pwsh
run: |
conda info -a
conda list
- name: Run all linters
shell: pwsh
run: |
pre-commit run --all-files
pre-commit run --all-files --verbose

View File

@ -34,10 +34,14 @@ repos:
rev: 3.8.3
hooks:
- id: flake8
exclude: tests/data
language_version: python3
additional_dependencies:
- flake8-typing-imports==1.9.0
- flake8-builtins==1.5.3
- flake8-bugbear==20.1.4
- flake8-isort==3.0.1
- repo: https://github.com/bmorcos/pre-commit-hooks-cpp
rev: master
hooks:
- id: clang-format
args: [--style=file]

View File

@ -7,9 +7,14 @@
#ifndef MAMBA_ACTIVATION_HPP
#define MAMBA_ACTIVATION_HPP
#include "util.hpp"
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "context.hpp"
#include "output.hpp"
#include "util.hpp"
// TODO write a map that keeps insertion order
@ -35,7 +40,6 @@ namespace mamba
class Activator
{
public:
virtual ~Activator() = default;
Activator(const Activator&) = delete;
@ -44,14 +48,17 @@ namespace mamba
Activator& operator=(Activator&&) = delete;
virtual std::string script(const EnvironmentTransform& env) = 0;
virtual std::pair<std::string, std::string> update_prompt(const std::string& conda_prompt_modifier) = 0;
virtual std::pair<std::string, std::string> update_prompt(
const std::string& conda_prompt_modifier)
= 0;
virtual std::string shell_extension() = 0;
std::vector<fs::path> get_activate_scripts(const fs::path& prefix);
std::vector<fs::path> get_deactivate_scripts(const fs::path& prefix);
std::string get_default_env(const fs::path& prefix);
std::vector<std::pair<std::string, std::string>> get_environment_vars(const fs::path& prefix);
std::vector<std::pair<std::string, std::string>> get_environment_vars(
const fs::path& prefix);
std::string get_prompt_modifier(const fs::path& prefix,
const std::string& conda_default_env,
@ -64,8 +71,9 @@ namespace mamba
std::string replace_prefix_in_path(const fs::path& old_prefix, const fs::path& new_prefix);
std::string remove_prefix_from_path(const fs::path& prefix);
void get_export_unset_vars(EnvironmentTransform& envt,
const std::vector<std::pair<std::string, std::string>>& to_export);
void get_export_unset_vars(
EnvironmentTransform& envt,
const std::vector<std::pair<std::string, std::string>>& to_export);
EnvironmentTransform build_reactivate();
EnvironmentTransform build_deactivate();
@ -82,7 +90,6 @@ namespace mamba
std::string hook();
protected:
Activator();
bool m_stack = false;
@ -94,12 +101,12 @@ namespace mamba
class PosixActivator : public Activator
{
public:
PosixActivator() = default;
virtual ~PosixActivator() = default;
std::string script(const EnvironmentTransform& env_transform) override;
std::pair<std::string, std::string> update_prompt(const std::string& conda_prompt_modifier) override;
std::pair<std::string, std::string> update_prompt(
const std::string& conda_prompt_modifier) override;
std::string shell_extension() override;
std::string hook_preamble() override;
@ -107,16 +114,15 @@ namespace mamba
fs::path hook_source_path() override;
};
class CmdExeActivator
: public Activator
class CmdExeActivator : public Activator
{
public:
CmdExeActivator() = default;
virtual ~CmdExeActivator() = default;
std::string script(const EnvironmentTransform& env_transform) override;
std::pair<std::string, std::string> update_prompt(const std::string& conda_prompt_modifier) override;
std::pair<std::string, std::string> update_prompt(
const std::string& conda_prompt_modifier) override;
std::string shell_extension() override;
std::string hook_preamble() override;
@ -124,15 +130,15 @@ namespace mamba
fs::path hook_source_path() override;
};
class PowerShellActivator
: public Activator
class PowerShellActivator : public Activator
{
public:
PowerShellActivator() = default;
virtual ~PowerShellActivator() = default;
std::string script(const EnvironmentTransform& env_transform) override;
std::pair<std::string, std::string> update_prompt(const std::string& conda_prompt_modifier) override;
std::pair<std::string, std::string> update_prompt(
const std::string& conda_prompt_modifier) override;
std::string shell_extension() override;
std::string hook_preamble() override;
@ -140,21 +146,21 @@ namespace mamba
fs::path hook_source_path() override;
};
class XonshActivator
: public Activator
class XonshActivator : public Activator
{
public:
XonshActivator() = default;
virtual ~XonshActivator() = default;
std::string script(const EnvironmentTransform& env_transform) override;
std::pair<std::string, std::string> update_prompt(const std::string& conda_prompt_modifier) override;
std::pair<std::string, std::string> update_prompt(
const std::string& conda_prompt_modifier) override;
std::string shell_extension() override;
std::string hook_preamble() override;
std::string hook_postamble() override;
fs::path hook_source_path() override;
};
}
} // namespace mamba
#endif

View File

@ -13,11 +13,9 @@
namespace mamba
{
class Channel
{
public:
Channel(const std::string& scheme = "",
const std::string& auth = "",
const std::string& location = "",
@ -52,7 +50,6 @@ namespace mamba
static void clear_cache();
private:
using cache_type = std::map<std::string, Channel>;
static cache_type& get_cache();
@ -60,8 +57,7 @@ namespace mamba
static Channel from_name(const std::string& name);
static Channel from_value(const std::string& value);
std::string build_url(const std::string& base,
bool with_credential) const;
std::string build_url(const std::string& base, bool with_credential) const;
std::string m_scheme;
std::string m_auth;
@ -89,7 +85,6 @@ namespace mamba
class ChannelContext
{
public:
using channel_list = std::vector<std::string>;
using channel_map = std::map<std::string, Channel>;
using multichannel_map = std::map<std::string, std::vector<std::string>>;
@ -108,7 +103,6 @@ namespace mamba
const channel_list& get_whitelist_channels() const;
private:
ChannelContext();
~ChannelContext() = default;
@ -121,6 +115,6 @@ namespace mamba
channel_list m_whitelist_channels;
};
}
} // namespace mamba
#endif

View File

@ -26,13 +26,13 @@ namespace mamba
class Context
{
public:
std::string conda_version = "3.8.0";
std::string current_command = "mamba";
fs::path target_prefix = std::getenv("CONDA_PREFIX") ? std::getenv("CONDA_PREFIX") : "";;
fs::path target_prefix = std::getenv("CONDA_PREFIX") ? std::getenv("CONDA_PREFIX") : "";
// Need to prevent circular imports here (otherwise using env::get())
fs::path root_prefix = std::getenv("MAMBA_ROOT_PREFIX") ? std::getenv("MAMBA_ROOT_PREFIX") : "";
fs::path root_prefix
= std::getenv("MAMBA_ROOT_PREFIX") ? std::getenv("MAMBA_ROOT_PREFIX") : "";
fs::path conda_prefix = root_prefix;
// TODO check writable and add other potential dirs
@ -40,7 +40,7 @@ namespace mamba
std::vector<fs::path> pkgs_dirs = { root_prefix / "pkgs" };
bool use_index_cache = false;
std::size_t local_repodata_ttl = 1; // take from header
std::size_t local_repodata_ttl = 1; // take from header
bool offline = false;
bool quiet = false;
bool json = false;
@ -63,9 +63,9 @@ namespace mamba
int connect_timeout_secs = 10;
// int read_timeout_secs = 60;
int retry_timeout = 2; // seconds
int retry_backoff = 3; // retry_timeout * retry_backoff
int max_retries = 3; // max number of retries
int retry_timeout = 2; // seconds
int retry_backoff = 3; // retry_timeout * retry_backoff
int max_retries = 3; // max number of retries
std::string env_prompt = "({default_env}) ";
@ -93,10 +93,9 @@ namespace mamba
Context& operator=(Context&&) = delete;
private:
Context();
~Context() = default;
};
}
} // namespace mamba
#endif // MAMBA_CONTEXT_HPP
#endif // MAMBA_CONTEXT_HPP

View File

@ -12,6 +12,8 @@
#include <cassert>
#include <string_view>
#include "util.hpp"
#include "thirdparty/filesystem.hpp"
namespace fs = ghc::filesystem;
@ -29,186 +31,189 @@ namespace fs = ghc::filesystem;
extern "C"
{
extern char **environ;
extern char** environ;
}
#endif
namespace mamba
{
namespace env
{
constexpr inline const char* pathsep()
namespace env
{
#ifdef _WIN32
return ";";
#else
return ":";
#endif
}
inline std::string get(const std::string& key)
{
const char* value = std::getenv(key.c_str());
if (!value) return "";
return value;
}
inline bool set(const std::string& key, const std::string& value)
{
#ifdef _WIN32
return SetEnvironmentVariable(key.c_str(), value.c_str());
#else
return setenv(key.c_str(), value.c_str(), 1) == 0;
#endif
}
inline fs::path which(const std::string& exe)
{
// TODO maybe add a cache?
if (std::getenv("PATH"))
constexpr inline const char* pathsep()
{
std::string path = std::getenv("PATH");
auto parts = split(path, pathsep());
for (auto& p : parts)
#ifdef _WIN32
return ";";
#else
return ":";
#endif
}
inline std::string get(const std::string& key)
{
const char* value = std::getenv(key.c_str());
if (!value)
return "";
return value;
}
inline bool set(const std::string& key, const std::string& value)
{
#ifdef _WIN32
return SetEnvironmentVariable(key.c_str(), value.c_str());
#else
return setenv(key.c_str(), value.c_str(), 1) == 0;
#endif
}
inline fs::path which(const std::string& exe)
{
// TODO maybe add a cache?
if (std::getenv("PATH"))
{
if (!fs::exists(p) || !fs::is_directory(p))
std::string path = std::getenv("PATH");
auto parts = mamba::split(path, pathsep());
for (auto& p : parts)
{
continue;
}
for (const auto & entry : fs::directory_iterator(p))
{
if (entry.path().filename() == exe)
if (!fs::exists(p) || !fs::is_directory(p))
{
return entry.path();
continue;
}
for (const auto& entry : fs::directory_iterator(p))
{
if (entry.path().filename() == exe)
{
return entry.path();
}
}
}
}
}
return ""; // empty path
}
inline std::map<std::string, std::string> copy()
{
std::map<std::string, std::string> m;
#ifndef _WIN32
int i = 1;
const char* c = *environ;
for (; c; i++)
{
std::string_view s(c);
auto pos = s.find("=");
m[std::string(s.substr(0, pos))] = (pos != s.npos) ? std::string(s.substr(pos + 1)) : "";
c = *(environ + i);
}
#else
// inspired by https://github.com/gennaroprota/breath/blob/0709a9f0fe4e745b1d9fc44ab65d92853820b515
// /breath/environment/brt/dep/syst/windows/get_environment_map.cpp#L38-L80
char* start = GetEnvironmentStrings();
if (start == nullptr)
{
throw std::runtime_error("GetEnvironmentStrings() failed") ;
return ""; // empty path
}
char* current = start;
while (*current != '\0')
inline std::map<std::string, std::string> copy()
{
std::string_view s = current;
auto pos = s.find("=");
assert (pos != std::string_view::npos);
std::string_view key = s.substr(0, pos) ;
if (!key.empty())
std::map<std::string, std::string> m;
#ifndef _WIN32
int i = 1;
const char* c = *environ;
for (; c; i++)
{
std::string_view value = (pos != s.npos) ? s.substr(pos + 1) : "";
m[std::string(key)] = value;
std::string_view s(c);
auto pos = s.find("=");
m[std::string(s.substr(0, pos))]
= (pos != s.npos) ? std::string(s.substr(pos + 1)) : "";
c = *(environ + i);
}
current += s.size() + 1;
#else
// inspired by
// https://github.com/gennaroprota/breath/blob/0709a9f0fe4e745b1d9fc44ab65d92853820b515
// /breath/environment/brt/dep/syst/windows/get_environment_map.cpp#L38-L80
char* start = GetEnvironmentStrings();
if (start == nullptr)
{
throw std::runtime_error("GetEnvironmentStrings() failed");
}
char* current = start;
while (*current != '\0')
{
std::string_view s = current;
auto pos = s.find("=");
assert(pos != std::string_view::npos);
std::string_view key = s.substr(0, pos);
if (!key.empty())
{
std::string_view value = (pos != s.npos) ? s.substr(pos + 1) : "";
m[std::string(key)] = value;
}
current += s.size() + 1;
}
#endif
return m;
}
#endif
return m;
inline std::string platform()
{
#ifndef _WIN32
utsname un;
int ret = uname(&un);
if (ret == -1)
{
throw std::runtime_error("uname() failed");
}
return std::string(un.sysname);
#else
return "win32";
#endif
}
inline fs::path home_directory()
{
#ifdef _WIN32
std::string maybe_home = env::get("USERPROFILE");
if (maybe_home.empty())
{
maybe_home = concat(env::get("HOMEDRIVE"), env::get("HOMEPATH"));
}
if (maybe_home.empty())
{
throw std::runtime_error(
"Cannot determine HOME (checked USERPROFILE, HOMEDRIVE and HOMEPATH env vars)");
}
#else
std::string maybe_home = env::get("HOME");
if (maybe_home.empty())
{
maybe_home = getpwuid(getuid())->pw_dir;
}
if (maybe_home.empty())
{
throw std::runtime_error("HOME not set.");
}
#endif
return maybe_home;
}
inline fs::path expand_user(const fs::path& path)
{
auto p = path.string();
if (p[0] == '~')
{
p.replace(0, 1, home_directory());
}
return p;
}
inline bool is_admin()
{
#ifdef _WIN32
return IsUserAnAdmin();
#else
return geteuid() == 0 || getegid() == 0;
#endif
}
// inline fs::path expand_vars(const fs::path& path)
// {
// #ifndef _WIN32
// wordexp_t w{};
// std::unique_ptr<wordexp_t, void(*)(wordexp_t*)> hold{&w, ::wordfree};
// ::wordexp(path.c_str(), &w, 0);
// if (w.we_wordc != 1)
// throw std::runtime_error("Cannot expand path: " + path.string());
// fs::path result = fs::absolute(w.we_wordv[0]);
// return result;
// #else
// // ExpandEnvironmentStringsW
// #endif
// }
}
inline std::string platform()
{
#ifndef _WIN32
utsname un;
int ret = uname(&un);
if (ret == -1)
{
throw std::runtime_error("uname() failed");
}
return std::string(un.sysname);
#else
return "win32";
#endif
}
inline fs::path home_directory()
{
#ifdef _WIN32
std::string maybe_home = env::get("USERPROFILE");
if (maybe_home.empty())
{
maybe_home = concat(env::get("HOMEDRIVE"), env::get("HOMEPATH"));
}
if (maybe_home.empty())
{
throw std::runtime_error("Cannot determine HOME (checked USERPROFILE, HOMEDRIVE and HOMEPATH env vars)");
}
#else
std::string maybe_home = env::get("HOME");
if (maybe_home.empty())
{
maybe_home = getpwuid(getuid())->pw_dir;
}
if (maybe_home.empty())
{
throw std::runtime_error("HOME not set.");
}
#endif
return maybe_home;
}
inline fs::path expand_user(const fs::path& path)
{
auto p = path.string();
if (p[0] == '~')
{
p.replace(0, 1, home_directory());
}
return p;
}
inline bool is_admin()
{
#ifdef _WIN32
return IsUserAnAdmin();
#else
return geteuid() == 0 || getegid() == 0;
#endif
}
// inline fs::path expand_vars(const fs::path& path)
// {
// #ifndef _WIN32
// wordexp_t w{};
// std::unique_ptr<wordexp_t, void(*)(wordexp_t*)> hold{&w, ::wordfree};
// ::wordexp(path.c_str(), &w, 0);
// if (w.we_wordc != 1)
// throw std::runtime_error("Cannot expand path: " + path.string());
// fs::path result = fs::absolute(w.we_wordv[0]);
// return result;
// #else
// // ExpandEnvironmentStringsW
// #endif
// }
}
}
#endif

View File

@ -7,15 +7,18 @@
#ifndef MAMBA_ENVIRONMENT_MANAGER
#define MAMBA_ENVIRONMENT_MANAGER
#include <limits>
#include <set>
#include <string>
#include <vector>
#include "util.hpp"
#include "environment.hpp"
#include "output.hpp"
#include "util.hpp"
namespace mamba
{
const std::string PREFIX_MAGIC_FILE = "conda-meta/history";
const char PREFIX_MAGIC_FILE[] = "conda-meta/history";
inline bool is_conda_environment(const fs::path& prefix)
{
@ -25,7 +28,6 @@ namespace mamba
class EnvironmentsManager
{
public:
void register_env(const fs::path& location)
{
fs::path env_txt_file = get_environments_txt_file(env::home_directory());
@ -37,12 +39,15 @@ namespace mamba
try
{
fs::create_directories(env_txt_file.parent_path());
} catch (...) {}
}
catch (...)
{
}
}
std::string final_location_string = remove_trailing_slash(final_location);
if (final_location_string.find("placehold_pl") != std::string::npos ||
final_location_string.find("skeleton_") != std::string::npos)
if (final_location_string.find("placehold_pl") != std::string::npos
|| final_location_string.find("skeleton_") != std::string::npos)
{
return;
}
@ -51,7 +56,8 @@ namespace mamba
for (auto& l : lines)
{
if (l == final_location_string) return;
if (l == final_location_string)
return;
}
std::ofstream out(env_txt_file, std::ios::app);
@ -60,11 +66,13 @@ namespace mamba
{
if (errno == EACCES || errno == EROFS || errno == ENOENT)
{
LOG_ERROR << "Could not register environment. " << env_txt_file << " not writeable or missing?";
LOG_ERROR << "Could not register environment. " << env_txt_file
<< " not writeable or missing?";
}
else
{
throw std::system_error(errno, std::system_category(), "failed to open " + env_txt_file.string());
throw std::system_error(
errno, std::system_category(), "failed to open " + env_txt_file.string());
}
}
}
@ -79,7 +87,7 @@ namespace mamba
std::size_t count = 0;
for (auto& _ : fs::directory_iterator(meta_dir))
{
(void)_;
(void) _;
++count;
}
if (count > 1)
@ -103,17 +111,19 @@ namespace mamba
// if (on_win)
// {
// fs::path home_dir_dir = env::home_directory().parent_path();
// search_dirs = tuple(join(home_dir_dir, d) for d in listdir(home_dir_dir))
// search_dirs = tuple(join(home_dir_dir, d) for d in
// listdir(home_dir_dir))
// }
// else
// {
// from pwd import getpwall
// search_dirs = tuple(pwentry.pw_dir for pwentry in getpwall()) or (expand('~'),)
// search_dirs = tuple(pwentry.pw_dir for pwentry in getpwall()) or
// (expand('~'),)
// }
// }
// else
{
search_dirs = std::vector<fs::path> { env::home_directory() };
search_dirs = std::vector<fs::path>{ env::home_directory() };
}
std::set<fs::path> all_env_paths;
@ -147,9 +157,8 @@ namespace mamba
}
private:
std::set<std::string>
clean_environments_txt(const fs::path& env_txt_file, const fs::path& location)
std::set<std::string> clean_environments_txt(const fs::path& env_txt_file,
const fs::path& location)
{
if (!fs::exists(env_txt_file))
return {};
@ -194,7 +203,6 @@ namespace mamba
return home / ".conda" / "environments.txt";
}
};
}
} // namespace mamba
#endif

View File

@ -7,32 +7,35 @@
#ifndef MAMBA_FETCH_HPP
#define MAMBA_FETCH_HPP
#include "nlohmann/json.hpp"
extern "C"
{
#include <archive.h>
#include <curl/curl.h>
}
#include <string>
#include <vector>
#include "nlohmann/json.hpp"
#include "output.hpp"
#include "validate.hpp"
extern "C"
{
#include <curl/curl.h>
#include <archive.h>
}
namespace mamba
{
class DownloadTarget
{
public:
DownloadTarget() = default;
DownloadTarget(const std::string& name, const std::string& url, const std::string& filename);
DownloadTarget(const std::string& name,
const std::string& url,
const std::string& filename);
~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);
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);
int progress_callback(void*, curl_off_t total_to_download, curl_off_t now_downloaded, curl_off_t, curl_off_t);
int progress_callback(
void*, curl_off_t total_to_download, curl_off_t now_downloaded, curl_off_t, curl_off_t);
void set_mod_etag_headers(const nlohmann::json& mod_etag);
void set_progress_bar(ProgressProxy progress_proxy);
void set_expected_size(std::size_t size);
@ -77,7 +80,6 @@ namespace mamba
std::string etag, mod, cache_control;
private:
std::function<bool()> m_finalize_callback;
std::string m_name, m_filename, m_url;
@ -106,7 +108,6 @@ namespace mamba
class MultiDownloadTarget
{
public:
MultiDownloadTarget();
~MultiDownloadTarget();
@ -115,12 +116,11 @@ namespace mamba
bool download(bool failfast);
private:
std::vector<DownloadTarget*> m_targets;
std::vector<DownloadTarget*> m_retry_targets;
CURLM* m_handle;
};
}
} // namespace mamba
#endif // MAMBA_FETCH_HPP
#endif // MAMBA_FETCH_HPP

View File

@ -4,97 +4,100 @@
//
// The full license is in the file LICENSE, distributed with this software.
#ifndef MAMBA_FS_UTIL
#define MAMBA_FS_UTIL
#include "util.hpp"
#include <string>
#include "environment.hpp"
#include "thirdparty/filesystem.hpp"
#include "util.hpp"
namespace fs = ghc::filesystem;
namespace mamba
{
namespace path
{
inline bool starts_with_home(const fs::path& p)
{
std::string path = p;
return path[0] == '~' || starts_with(env::expand_user(path).string(), env::expand_user("~").string());
}
namespace path
{
inline bool starts_with_home(const fs::path& p)
{
std::string path = p;
return path[0] == '~'
|| starts_with(env::expand_user(path).string(), env::expand_user("~").string());
}
// TODO more error handling
inline void create_directories_sudo_safe(const fs::path& path)
{
if (fs::is_directory(path)) return;
// TODO more error handling
inline void create_directories_sudo_safe(const fs::path& path)
{
if (fs::is_directory(path))
return;
fs::path base_dir = path.parent_path();
if (!fs::is_directory(base_dir))
{
create_directories_sudo_safe(base_dir);
}
fs::create_directory(path);
fs::path base_dir = path.parent_path();
if (!fs::is_directory(base_dir))
{
create_directories_sudo_safe(base_dir);
}
fs::create_directory(path);
#ifndef _WIN32
// set permissions to 0o2775
fs::permissions(path, fs::perms::set_gid |
fs::perms::owner_all |
fs::perms::group_all |
fs::perms::others_read | fs::perms::others_exec);
#endif
}
#ifndef _WIN32
// set permissions to 0o2775
fs::permissions(path,
fs::perms::set_gid | fs::perms::owner_all | fs::perms::group_all
| fs::perms::others_read | fs::perms::others_exec);
#endif
}
inline bool touch(fs::path path, bool mkdir=false, bool sudo_safe=false)
{
// TODO error handling!
path = env::expand_user(path);
if (lexists(path))
{
fs::last_write_time(path, fs::file_time_type::clock::now());
return true;
}
else
{
auto dirpath = path.parent_path();
if (!fs::is_directory(dirpath) && mkdir)
{
if (sudo_safe)
{
create_directories_sudo_safe(dirpath);
}
else
{
fs::create_directories(dirpath);
}
}
// directory exists, now create empty file
std::ofstream(path, std::ios::out);
return false;
}
}
inline bool touch(fs::path path, bool mkdir = false, bool sudo_safe = false)
{
// TODO error handling!
path = env::expand_user(path);
if (lexists(path))
{
fs::last_write_time(path, fs::file_time_type::clock::now());
return true;
}
else
{
auto dirpath = path.parent_path();
if (!fs::is_directory(dirpath) && mkdir)
{
if (sudo_safe)
{
create_directories_sudo_safe(dirpath);
}
else
{
fs::create_directories(dirpath);
}
}
// directory exists, now create empty file
std::ofstream(path, std::ios::out);
return false;
}
}
inline bool is_writable(const fs::path& path)
{
if (fs::is_directory(path.parent_path()))
{
bool path_existed = lexists(path);
std::ofstream test;
test.open(path);
bool is_writable = test.is_open();
if (!path_existed)
{
test.close();
fs::remove(path);
}
return is_writable;
}
else
{
throw std::runtime_error("Cannot check file path at " + path.string() + " for accessibility.");
}
}
}
}
inline bool is_writable(const fs::path& path)
{
if (fs::is_directory(path.parent_path()))
{
bool path_existed = lexists(path);
std::ofstream test;
test.open(path);
bool is_writable = test.is_open();
if (!path_existed)
{
test.close();
fs::remove(path);
}
return is_writable;
}
else
{
throw std::runtime_error("Cannot check file path at " + path.string()
+ " for accessibility.");
}
}
} // namespace path
} // namespace mamba
#endif

View File

@ -8,11 +8,11 @@
#define MAMBA_GRAPH_UTIL_HPP
#include <map>
#include <utility>
#include <vector>
namespace mamba
{
// Simplified implementation of a directed graph
// where a path exists between each node and the
// first one (you can think of it as a tree with
@ -22,7 +22,6 @@ namespace mamba
class graph
{
public:
using node = T;
using node_id = size_t;
using node_list = std::vector<node>;
@ -41,7 +40,6 @@ namespace mamba
void depth_first_search(V& visitor, node_id start = node_id(0)) const;
private:
enum class color
{
white,
@ -65,35 +63,47 @@ namespace mamba
class default_visitor
{
public:
using graph_type = G;
using node_id = typename graph_type::node_id;
void start_node(node_id, const G&) {}
void finish_node(node_id, const G&) {}
void start_node(node_id, const G&)
{
}
void finish_node(node_id, const G&)
{
}
void start_edge(node_id, node_id, const G&) {}
void tree_edge(node_id, node_id, const G&) {}
void back_edge(node_id, node_id, const G&) {}
void forward_or_cross_edge(node_id, node_id, const G&) {}
void finish_edge(node_id, node_id, const G&) {}
void start_edge(node_id, node_id, const G&)
{
}
void tree_edge(node_id, node_id, const G&)
{
}
void back_edge(node_id, node_id, const G&)
{
}
void forward_or_cross_edge(node_id, node_id, const G&)
{
}
void finish_edge(node_id, node_id, const G&)
{
}
};
template <class G>
class predecessor_recorder : private default_visitor<G>
{
public:
using base_type = default_visitor<G>;
using graph_type = typename base_type::graph_type;
using node_id = typename base_type::node_it;
using predecessor_map = std::map<node_id, node_id>;
using base_type::start_node;
using base_type::finish_node;
using base_type::start_edge;
using base_type::back_edge;
using base_type::finish_node;
using base_type::forward_or_cross_edge;
using base_type::start_edge;
using base_type::start_node;
void tree_edge(node_id from, node_id to, const G&);
void finish_edge(node_id id, const G&);
@ -101,7 +111,6 @@ namespace mamba
const predecessor_map& get_predecessors() const;
private:
predecessor_map m_pred;
};
@ -109,7 +118,6 @@ namespace mamba
class composite_visitor
{
public:
using graph_type = G;
using node_id = typename G::node_id;
@ -125,7 +133,6 @@ namespace mamba
void finish_edge(node_id, node_id, const G&);
private:
V1<G> m_v1;
V2<G> m_v2;
};
@ -141,7 +148,7 @@ namespace mamba
}
template <class T>
inline auto graph<T>::get_edge_list(node_id id) const -> const edge_list&
inline auto graph<T>::get_edge_list(node_id id) const -> const edge_list&
{
return m_adjacency_list[id];
}
@ -186,11 +193,13 @@ namespace mamba
template <class T>
template <class V>
inline void graph<T>::depth_first_search_impl(V& visitor, node_id node, color_list& colors) const
inline void graph<T>::depth_first_search_impl(V& visitor,
node_id node,
color_list& colors) const
{
colors[node] = color::gray;
visitor.start_node(node, *this);
for (auto child: m_adjacency_list[node])
for (auto child : m_adjacency_list[node])
{
visitor.start_edge(node, child, *this);
if (colors[child] == color::white)
@ -240,7 +249,8 @@ namespace mamba
template <class G, template <class> class V1, template <class> class V2>
inline composite_visitor<G, V1, V2>::composite_visitor(V1<G> v1, V2<G> v2)
: m_v1(v1), m_v2(v2)
: m_v1(v1)
, m_v2(v2)
{
}
@ -280,7 +290,9 @@ namespace mamba
}
template <class G, template <class> class V1, template <class> class V2>
inline void composite_visitor<G, V1, V2>::forward_or_cross_edge(node_id from, node_id to, const G& g)
inline void composite_visitor<G, V1, V2>::forward_or_cross_edge(node_id from,
node_id to,
const G& g)
{
m_v1.forward_or_cross_edge(from, to, g);
m_v2.forward_or_cross_edge(from, to, g);
@ -292,6 +304,6 @@ namespace mamba
m_v1.finish_edge(from, to, g);
m_v2.finish_edge(from, to, g);
}
}
} // namespace mamba
#endif
#endif // INCLUDE_GRAPH_UTIL_HPP

View File

@ -7,78 +7,70 @@
#ifndef MAMBA_HISTORY
#define MAMBA_HISTORY
#include <vector>
#include <regex>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
#include "thirdparty/filesystem.hpp"
#include "output.hpp"
// #include "prefix_data.hpp"
#include "match_spec.hpp"
#include "output.hpp"
#include "thirdparty/filesystem.hpp"
namespace fs = ghc::filesystem;
namespace mamba
{
class History
{
public:
// History(const std::shared_ptr<PrefixData>& prefix)
// : m_prefix_data(prefix)
// {
// }
History(const std::string& prefix);
struct ParseResult
class History
{
std::string head_line;
std::set<std::string> diff;
std::vector<std::string> comments;
};
public:
History(const std::string& prefix);
struct UserRequest
{
static UserRequest prefilled()
struct ParseResult
{
UserRequest ur;
std::time_t t = std::time(nullptr);
char mbstr[100];
if (std::strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %H:%M:%S", std::localtime(&t)))
std::string head_line;
std::set<std::string> diff;
std::vector<std::string> comments;
};
struct UserRequest
{
static UserRequest prefilled()
{
ur.date = mbstr;
UserRequest ur;
std::time_t t = std::time(nullptr);
char mbstr[100];
if (std::strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %H:%M:%S", std::localtime(&t)))
{
ur.date = mbstr;
}
ur.cmd = Context::instance().current_command;
ur.conda_version = Context::instance().conda_version;
return ur;
}
ur.cmd = Context::instance().current_command;
ur.conda_version = Context::instance().conda_version;
return ur;
}
std::string date;
std::string cmd;
std::string conda_version;
std::string date;
std::string cmd;
std::string conda_version;
std::vector<std::string> unlink_dists;
std::vector<std::string> link_dists;
std::vector<std::string> unlink_dists;
std::vector<std::string> link_dists;
std::vector<std::string> update;
std::vector<std::string> remove;
std::vector<std::string> neutered;
std::vector<std::string> update;
std::vector<std::string> remove;
std::vector<std::string> neutered;
};
std::vector<ParseResult> parse();
bool parse_comment_line(const std::string& line, UserRequest& req);
std::vector<UserRequest> get_user_requests();
std::unordered_map<std::string, MatchSpec> get_requested_specs_map();
void add_entry(const History::UserRequest& entry);
std::string m_prefix;
fs::path m_history_file_path;
};
std::vector<ParseResult> parse();
bool parse_comment_line(const std::string& line, UserRequest& req);
std::vector<UserRequest> get_user_requests();
std::unordered_map<std::string, MatchSpec> get_requested_specs_map();
void add_entry(const History::UserRequest& entry);
// std::shared_ptr<PrefixData> m_prefix_data;
std::string m_prefix;
fs::path m_history_file_path;
};
}
} // namespace mamba
#endif

View File

@ -9,64 +9,68 @@
#include <iostream>
#include <stack>
#include <string>
#include <tuple>
#include <vector>
#include "nlohmann/json.hpp"
#include "thirdparty/filesystem.hpp"
#include "transaction.hpp"
#include "match_spec.hpp"
#include "transaction_context.hpp"
#include "nlohmann/json.hpp"
#include "package_paths.hpp"
#include "thirdparty/filesystem.hpp"
#include "transaction.hpp"
#include "transaction_context.hpp"
namespace fs = ghc::filesystem;
namespace mamba
{
struct python_entry_point_parsed
{
std::string command, module, func;
};
struct python_entry_point_parsed
{
std::string command, module, func;
};
class UnlinkPackage
{
public:
UnlinkPackage(const PackageInfo& pkg_info,
const fs::path& cache_path,
TransactionContext* context);
class UnlinkPackage
{
public:
UnlinkPackage(const PackageInfo& pkg_info, const fs::path& cache_path, TransactionContext* context);
bool execute();
bool undo();
bool execute();
bool undo();
private:
bool unlink_path(const nlohmann::json& path_data);
private:
PackageInfo m_pkg_info;
fs::path m_cache_path;
std::string m_specifier;
TransactionContext* m_context;
};
bool unlink_path(const nlohmann::json& path_data);
class LinkPackage
{
public:
LinkPackage(const PackageInfo& pkg_info,
const fs::path& cache_path,
TransactionContext* context);
PackageInfo m_pkg_info;
fs::path m_cache_path;
std::string m_specifier;
TransactionContext* m_context;
};
bool execute();
bool undo();
class LinkPackage
{
public:
private:
std::tuple<std::string, std::string> link_path(const PathData& path_data,
bool noarch_python);
std::vector<fs::path> compile_pyc_files(const std::vector<fs::path>& py_files);
auto create_python_entry_point(const fs::path& path,
const python_entry_point_parsed& entry_point);
LinkPackage(const PackageInfo& pkg_info, const fs::path& cache_path, TransactionContext* context);
PackageInfo m_pkg_info;
fs::path m_cache_path;
fs::path m_source;
TransactionContext* m_context;
};
bool execute();
bool undo();
private:
std::tuple<std::string, std::string> link_path(const PathData& path_data, bool noarch_python);
std::vector<fs::path> compile_pyc_files(const std::vector<fs::path>& py_files);
auto create_python_entry_point(const fs::path& path, const python_entry_point_parsed& entry_point);
PackageInfo m_pkg_info;
fs::path m_cache_path;
fs::path m_source;
TransactionContext* m_context;
};
}
} // namespace mamba
#endif

View File

@ -9,6 +9,7 @@
#include <regex>
#include <string>
#include <tuple>
#include <unordered_map>
namespace mamba
@ -16,7 +17,6 @@ namespace mamba
class MatchSpec
{
public:
MatchSpec() = default;
MatchSpec(const std::string& i_spec);
@ -43,6 +43,6 @@ namespace mamba
std::unordered_map<std::string, std::string> brackets;
std::unordered_map<std::string, std::string> parens;
};
}
} // namespace mamba
#endif

View File

@ -7,35 +7,50 @@
#ifndef MAMBA_OUTPUT_HPP
#define MAMBA_OUTPUT_HPP
#include <string_view>
#include <iostream>
#include <iomanip>
#include <chrono>
#include <string>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "context.hpp"
#include "nlohmann/json.hpp"
#define ENUM_FLAG_OPERATOR(T,X) inline T operator X (T lhs, T rhs) { return (T) (static_cast<std::underlying_type_t <T>>(lhs) X static_cast<std::underlying_type_t <T>>(rhs)); }
#define ENUM_FLAGS(T) \
enum class T; \
inline T operator ~ (T t) { return (T) (~static_cast<std::underlying_type_t <T>>(t)); } \
ENUM_FLAG_OPERATOR(T,|) \
ENUM_FLAG_OPERATOR(T,^) \
ENUM_FLAG_OPERATOR(T,&) \
enum class T
#define ENUM_FLAG_OPERATOR(T, X) \
inline T operator X(T lhs, T rhs) \
{ \
return (T)(static_cast<std::underlying_type_t<T>>(lhs) \
X static_cast<std::underlying_type_t<T>>(rhs)); \
}
#define ENUM_FLAGS(T) \
enum class T; \
inline T operator~(T t) \
{ \
return (T)(~static_cast<std::underlying_type_t<T>>(t)); \
} \
ENUM_FLAG_OPERATOR(T, |) \
ENUM_FLAG_OPERATOR(T, ^) \
ENUM_FLAG_OPERATOR(T, &) \
enum class T
#define PREFIX_LENGTH 25
namespace cursor
{
class CursorMovementTriple {
class CursorMovementTriple
{
public:
CursorMovementTriple(const char* esc, int n, const char* mod)
: m_esc(esc), m_mod(mod), m_n(n)
{}
: m_esc(esc)
, m_mod(mod)
, m_n(n)
{
}
const char* m_esc;
const char* m_mod;
@ -48,11 +63,13 @@ namespace cursor
return o;
}
class CursorMod {
class CursorMod
{
public:
CursorMod(const char* mod)
: m_mod(mod)
{}
{
}
std::ostream& operator<<(std::ostream& o)
{
@ -112,20 +129,19 @@ namespace cursor
{
return CursorMod("\x1b[?25l");
}
}
} // namespace cursor
namespace mamba
{
std::string cut_repo_name(const std::string& reponame);
namespace printers
{
enum class format : std::size_t {
none = 0,
red = 1 << 1,
green = 1 << 2,
enum class format : std::size_t
{
none = 0,
red = 1 << 1,
green = 1 << 2,
yellow = 1 << 3
};
@ -139,12 +155,12 @@ namespace mamba
inline FormattedString(const std::string& i)
: s(i)
{
};
}
inline FormattedString(const char* i)
: s(i)
{
};
}
inline std::size_t size() const
{
@ -154,21 +170,21 @@ namespace mamba
enum class alignment : std::size_t
{
left = 1 << 1,
left = 1 << 1,
right = 1 << 2,
fill = 1 << 3
fill = 1 << 3
};
class Table
{
public:
Table(const std::vector<FormattedString>& header);
void set_alignment(const std::vector<alignment>& a);
void set_padding(const std::vector<int>& p);
void add_row(const std::vector<FormattedString>& r);
void add_rows(const std::string& header, const std::vector<std::vector<FormattedString>>& rs);
void add_rows(const std::string& header,
const std::vector<std::vector<FormattedString>>& rs);
std::ostream& print(std::ostream& out);
@ -178,18 +194,16 @@ namespace mamba
std::vector<int> m_padding;
std::vector<std::vector<FormattedString>> m_table;
};
}
} // namespace printers
// The next two functions / classes were ported from the awesome indicators library
// by p-ranav (MIT License)
// https://github.com/p-ranav/indicators
std::ostream& write_duration(std::ostream &os, std::chrono::nanoseconds ns);
// The next two functions / classes were ported from the awesome indicators
// library by p-ranav (MIT License) https://github.com/p-ranav/indicators
std::ostream& write_duration(std::ostream& os, std::chrono::nanoseconds ns);
int get_console_width();
class ProgressScaleWriter
{
public:
inline ProgressScaleWriter(int bar_width,
const std::string& fill,
const std::string& lead,
@ -198,7 +212,6 @@ namespace mamba
std::ostream& write(std::ostream& os, std::size_t progress) const;
private:
int m_bar_width;
std::string m_fill;
std::string m_lead;
@ -208,7 +221,6 @@ namespace mamba
class ProgressBar
{
public:
ProgressBar(const std::string& prefix);
void set_start();
@ -220,7 +232,6 @@ namespace mamba
const std::string& prefix() const;
private:
std::chrono::nanoseconds m_elapsed_ns;
std::chrono::time_point<std::chrono::high_resolution_clock> m_start_time;
@ -232,7 +243,6 @@ namespace mamba
class ProgressProxy
{
public:
ProgressProxy() = default;
~ProgressProxy() = default;
@ -247,7 +257,6 @@ namespace mamba
void mark_as_completed(const std::string_view& final_message = "");
private:
ProgressProxy(ProgressBar* ptr, std::size_t idx);
ProgressBar* p_bar;
@ -261,7 +270,6 @@ namespace mamba
class ConsoleStream : public std::stringstream
{
public:
ConsoleStream() = default;
~ConsoleStream();
};
@ -269,7 +277,6 @@ namespace mamba
class Console
{
public:
Console(const Console&) = delete;
Console& operator=(const Console&) = delete;
@ -279,14 +286,13 @@ namespace mamba
static Console& instance();
static ConsoleStream stream();
static void print(const std::string_view& str, bool force_print=false);
static bool prompt(const std::string_view& message, char fallback='_');
static void print(const std::string_view& str, bool force_print = false);
static bool prompt(const std::string_view& message, char fallback = '_');
ProgressProxy add_progress_bar(const std::string& name);
void init_multi_progress();
private:
using progress_bar_ptr = std::unique_ptr<ProgressBar>;
Console();
@ -330,7 +336,6 @@ namespace mamba
class MessageLogger
{
public:
MessageLogger(const char* file, int line, LogSeverity severity);
~MessageLogger();
@ -339,18 +344,15 @@ namespace mamba
static LogSeverity& global_log_severity();
private:
std::string m_file;
int m_line;
LogSeverity m_severity;
std::stringstream m_stream;
};
class JsonLogger
{
public:
JsonLogger(const JsonLogger&) = delete;
JsonLogger& operator=(const JsonLogger&) = delete;
@ -367,14 +369,13 @@ namespace mamba
void json_up();
private:
JsonLogger();
~JsonLogger() = default;
std::string json_hier;
unsigned int json_index;
};
}
} // namespace mamba
#undef ERROR
#undef WARNING
@ -387,4 +388,4 @@ namespace mamba
#define LOG_ERROR LOG(mamba::LogSeverity::error)
#define LOG_FATAL LOG(mamba::LogSeverity::fatal)
#endif // MAMBA_OUTPUT_HPP
#endif // MAMBA_OUTPUT_HPP

View File

@ -7,14 +7,15 @@
#ifndef MAMBA_PACKAGE_CACHE
#define MAMBA_PACKAGE_CACHE
#include <vector>
#include <string>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include "output.hpp"
#include "context.hpp"
#include "fsutil.hpp"
#include "environment.hpp"
#include "fsutil.hpp"
#include "output.hpp"
#include "package_info.hpp"
#define PACKAGE_CACHE_MAGIC_FILE "urls.txt"
@ -33,7 +34,6 @@ namespace mamba
class PackageCacheData
{
public:
PackageCacheData(const fs::path& pkgs_dir);
bool create_directory();
@ -46,7 +46,6 @@ namespace mamba
static PackageCacheData first_writable(const std::vector<fs::path>* pkgs_dirs = nullptr);
private:
void check_writable();
std::map<std::string, bool> m_valid_cache;
@ -65,6 +64,6 @@ namespace mamba
private:
std::vector<PackageCacheData> m_caches;
};
}
} // namespace mamba
#endif

View File

@ -7,7 +7,10 @@
#ifndef MAMBA_PACKAGE_HANDLING_HPP
#define MAMBA_PACKAGE_HANDLING_HPP
#include <string>
#include <system_error>
#include <vector>
#include "thirdparty/filesystem.hpp"
namespace fs = ghc::filesystem;
@ -15,10 +18,14 @@ namespace fs = ghc::filesystem;
namespace mamba
{
void extract_archive(const fs::path& file, const fs::path& destination);
void extract_conda(const fs::path& file, const fs::path& dest_dir, const std::vector<std::string>& parts = {"info", "pkg"});
void split_package_extension(const std::string& file, std::string& name, std::string& extension);
void extract_conda(const fs::path& file,
const fs::path& dest_dir,
const std::vector<std::string>& parts = { "info", "pkg" });
void split_package_extension(const std::string& file,
std::string& name,
std::string& extension);
fs::path strip_package_extension(const std::string& file);
fs::path extract(const fs::path& file);
}
} // namespace mamba
#endif // MAMBA_PACKAGE_HANDLING_HPP
#endif // MAMBA_PACKAGE_HANDLING_HPP

View File

@ -7,15 +7,17 @@
#ifndef MAMBA_PACKAGE_INFO
#define MAMBA_PACKAGE_INFO
#include <string>
extern "C" {
#include <solv/solvable.h>
#include <solv/pool.h>
#include <solv/repo.h>
#include <solv/poolid.h>
extern "C"
{
#include <solv/pool.h>
#include <solv/poolid.h>
#include <solv/repo.h>
#include <solv/solvable.h>
}
#include <string>
#include <vector>
#include "nlohmann/json.hpp"
namespace mamba
@ -23,9 +25,8 @@ namespace mamba
class PackageInfo
{
public:
using field_getter = std::function<std::string (const PackageInfo&)>;
using compare_fun = std::function<bool (const PackageInfo&, const PackageInfo&)>;
using field_getter = std::function<std::string(const PackageInfo&)>;
using compare_fun = std::function<bool(const PackageInfo&, const PackageInfo&)>;
static field_getter get_field_getter(const std::string& name);
static compare_fun less(const std::string& member);
@ -34,8 +35,10 @@ namespace mamba
PackageInfo(Solvable* s);
PackageInfo(nlohmann::json&& j);
PackageInfo(const std::string& name);
PackageInfo(const std::string& name, const std::string& version,
const std::string build_string, std::size_t build_number);
PackageInfo(const std::string& name,
const std::string& version,
const std::string build_string,
std::size_t build_number);
nlohmann::json json() const;
std::string str() const;
@ -57,6 +60,6 @@ namespace mamba
std::vector<std::string> depends;
std::vector<std::string> constrains;
};
}
} // namespace mamba
#endif

View File

@ -7,19 +7,22 @@
#ifndef MAMBA_READ_PATHS_HPP
#define MAMBA_READ_PATHS_HPP
#include "util.hpp"
#include <string>
#include <map>
#include <set>
#include <string>
#include <vector>
const std::string PREFIX_PLACEHOLDER_1("/opt/anaconda1anaconda2");
// this is intentionally split into parts, such that running
// this program on itself will leave it unchanged
const std::string PREFIX_PLACEHOLDER_2("anaconda3");
#include "util.hpp"
const char PREFIX_PLACEHOLDER_1[] = "/opt/anaconda1anaconda2";
// this is intentionally split into parts, such that running
// this program on itself will leave it unchanged
const char PREFIX_PLACEHOLDER_2[] = "anaconda3";
namespace mamba
{
struct PrefixFileParse {
struct PrefixFileParse
{
std::string placeholder;
std::string file_mode;
std::string file_path;
@ -62,6 +65,6 @@ namespace mamba
std::map<std::string, PrefixFileParse> read_has_prefix(const fs::path& path);
std::set<std::string> read_no_link(const fs::path& info_dir);
std::vector<PathData> read_paths(const fs::path& directory);
}
} // namespace mamba
#endif

View File

@ -11,7 +11,7 @@
extern "C"
{
#include "solv/pool.h"
#include "solv/pool.h"
}
namespace mamba
@ -19,7 +19,6 @@ namespace mamba
class MPool
{
public:
MPool();
~MPool();
@ -34,9 +33,8 @@ namespace mamba
operator Pool*();
private:
Pool* m_pool;
};
}
} // namespace mamba
#endif // MAMBA_POOL_HPP
#endif // MAMBA_POOL_HPP

View File

@ -7,10 +7,11 @@
#ifndef MAMBA_PREFIX_DATA_HPP
#define MAMBA_PREFIX_DATA_HPP
#include <string>
#include <unordered_map>
#include "package_info.hpp"
#include "history.hpp"
#include "package_info.hpp"
#include "util.hpp"
namespace mamba
@ -33,6 +34,6 @@ namespace mamba
std::unordered_map<std::string, PackageInfo> m_package_records;
fs::path m_prefix_path;
};
}
} // namespace mamba
#endif

View File

@ -7,38 +7,45 @@
#ifndef MAMBA_QUERY_HPP
#define MAMBA_QUERY_HPP
#include <algorithm>
#include <deque>
#include <functional>
#include <map>
#include <ostream>
#include <string>
#include <string_view>
#include <vector>
#include "graph_util.hpp"
#include "output.hpp"
#include "package_info.hpp"
#include "pool.hpp"
#include "graph_util.hpp"
extern "C"
{
#include "solv/repo.h"
#include "solv/conda.h"
#include "solv/solver.h"
#include "solv/selection.h"
#include "solv/conda.h"
#include "solv/repo.h"
#include "solv/selection.h"
#include "solv/solver.h"
}
namespace nl = nlohmann;
namespace mamba
{
void print_dep_graph(std::ostream& out, Solvable* s, const std::string& solv_str, int level, int max_level, bool last, const std::string& prefix);
void print_dep_graph(std::ostream& out,
Solvable* s,
const std::string& solv_str,
int level,
int max_level,
bool last,
const std::string& prefix);
class query_result;
class Query
{
public:
Query(MPool& pool);
query_result find(const std::string& query) const;
@ -46,7 +53,6 @@ namespace mamba
query_result depends(const std::string& query, bool tree) const;
private:
std::reference_wrapper<MPool> m_pool;
};
@ -60,14 +66,11 @@ namespace mamba
class query_result
{
public:
using dependency_graph = graph<PackageInfo>;
using package_list = dependency_graph::node_list;
using package_view_list = std::vector<package_list::const_iterator>;
query_result(QueryType type,
const std::string& query,
dependency_graph&& dep_graph);
query_result(QueryType type, const std::string& query, dependency_graph&& dep_graph);
~query_result() = default;
@ -88,7 +91,6 @@ namespace mamba
nl::json json() const;
private:
void reset_pkg_view_list();
std::string get_package_repr(const PackageInfo& pkg) const;
@ -99,6 +101,6 @@ namespace mamba
using ordered_package_list = std::map<std::string, package_view_list>;
ordered_package_list m_ordered_pkg_list;
};
}
} // namespace mamba
#endif // MAMBA_QUERY_HPP
#endif // MAMBA_QUERY_HPP

View File

@ -14,10 +14,10 @@
extern "C"
{
#include "solv/repo.h"
#include "solv/repo_solv.h"
#include "solv/conda.h"
#include "solv/repo_conda.h"
#include "solv/conda.h"
#include "solv/repo.h"
#include "solv/repo_conda.h"
#include "solv/repo_solv.h"
}
#include "pool.hpp"
@ -34,17 +34,18 @@ namespace mamba
inline bool operator==(const RepoMetadata& lhs, const RepoMetadata& rhs)
{
return lhs.url == rhs.url && lhs.pip_added == rhs.pip_added &&
lhs.etag == rhs.etag && lhs.mod == rhs.mod;
return lhs.url == rhs.url && lhs.pip_added == rhs.pip_added && lhs.etag == rhs.etag
&& lhs.mod == rhs.mod;
}
class MRepo
{
public:
MRepo(MPool& pool, const PrefixData& prefix_data);
MRepo(MPool& pool, const std::string& name,
const std::string& filename, const std::string& url);
MRepo(MPool& pool,
const std::string& name,
const std::string& filename,
const std::string& url);
MRepo(MPool& pool, const std::string& name, const fs::path& path, const RepoMetadata& meta);
~MRepo();
@ -61,7 +62,6 @@ namespace mamba
bool clear(bool reuse_ids);
private:
bool read_file(const std::string& filename);
std::string m_json_file, m_solv_file;
@ -71,6 +71,6 @@ namespace mamba
Repo* m_repo;
};
}
} // namespace mamba
#endif // MAMBA_REPO_HPP
#endif // MAMBA_REPO_HPP

View File

@ -22,43 +22,43 @@ namespace fs = ghc::filesystem;
#include "thirdparty/termcolor.hpp"
#ifndef _WIN32
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#endif
#include <inttypes.h>
#if defined(__linux__)
#include <linux/limits.h>
#else
#include <limits.h>
#endif
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#endif
#include <inttypes.h>
#if defined(__linux__)
#include <linux/limits.h>
#else
#include <windows.h>
#include <intrin.h>
#include "thirdparty/WinReg.hpp"
#include <limits.h>
#endif
#else
#include <windows.h>
#include <intrin.h>
#include "thirdparty/WinReg.hpp"
#endif
// Here we are embedding the shell scripts
constexpr const char mamba_sh[] =
#include "../data/mamba.sh"
;
#include "../data/mamba.sh"
;
constexpr const char mamba_bat[] =
#include "../data/mamba.bat"
;
#include "../data/mamba.bat"
;
constexpr const char _mamba_activate_bat[] =
#include "../data/_mamba_activate.bat"
;
#include "../data/_mamba_activate.bat"
;
constexpr const char mamba_hook_bat[] =
#include "../data/mamba_hook.bat"
;
#include "../data/mamba_hook.bat"
;
constexpr const char mamba_hook_ps1[] =
#include "../data/mamba_hook.ps1"
;
#include "../data/mamba_hook.ps1"
;
constexpr const char mamba_psm1[] =
#include "../data/Mamba.psm1"
;
#include "../data/Mamba.psm1"
;
constexpr const char mamba_xsh[] =
#include "../data/mamba.xsh"
;
#include "../data/mamba.xsh"
;
namespace mamba
{
@ -88,13 +88,17 @@ namespace mamba
return "";
}
#ifdef _WIN32
void init_cmd_exe_registry(const std::wstring& reg_path, const fs::path& conda_prefix, bool reverse = false)
#ifdef _WIN32
void init_cmd_exe_registry(const std::wstring& reg_path,
const fs::path& conda_prefix,
bool reverse = false)
{
winreg::RegKey key{ HKEY_CURRENT_USER, reg_path };
std::wstring prev_value = key.GetStringValue(L"AutoRun");
std::wstring prev_value = key.GetStringValue(L"AutoRun");
// std::wstring hook_path = '"%s"' % join(conda_prefix, 'condabin', 'conda_hook.bat')
std::wstring hook_string = std::wstring(L"\"") + (conda_prefix / "condabin" / "mamba_hook.bat").wstring() + std::wstring(L"\"");
std::wstring hook_string = std::wstring(L"\"")
+ (conda_prefix / "condabin" / "mamba_hook.bat").wstring()
+ std::wstring(L"\"");
if (reverse)
{
@ -103,13 +107,10 @@ namespace mamba
else
{
std::wstring replace_str(L"__CONDA_REPLACE_ME_123__");
std::wregex hook_regex(L"(\"[^\"]*?mamba[-_]hook\\.bat\")", std::regex_constants::icase);
std::wregex hook_regex(L"(\"[^\"]*?mamba[-_]hook\\.bat\")",
std::regex_constants::icase);
prev_value = std::regex_replace(
prev_value,
hook_regex,
replace_str,
std::regex_constants::format_first_only
);
prev_value, hook_regex, replace_str, std::regex_constants::format_first_only);
replace_all(prev_value, replace_str, hook_string);
std::wstring new_value = prev_value;
@ -134,13 +135,13 @@ namespace mamba
}
}
}
#endif
#endif
// Heavily inspired by https://github.com/gpakosz/whereami/
// check their source to add support for other OS
fs::path get_self_exe_path()
{
#ifdef _WIN32
#ifdef _WIN32
DWORD size;
std::wstring buffer(MAX_PATH, '\0');
size = GetModuleFileNameW(NULL, (wchar_t*) buffer.c_str(), (DWORD) buffer.size());
@ -151,14 +152,15 @@ namespace mamba
else if (size == buffer.size())
{
DWORD new_size = size;
do {
do
{
new_size *= 2;
buffer.reserve(new_size);
size = GetModuleFileNameW(NULL, (wchar_t*) buffer.c_str(), (DWORD) buffer.size());
} while (new_size == size);
}
return fs::absolute(buffer);
#elif defined(__APPLE__)
#elif defined(__APPLE__)
uint32_t size = PATH_MAX;
std::vector<char> buffer(size);
if (_NSGetExecutablePath(buffer.data(), &size) == -1)
@ -170,13 +172,13 @@ namespace mamba
}
}
return fs::absolute(buffer.data());
#else
#if defined(__sun)
return fs::read_symlink("/proc/self/path/a.out");
#else
return fs::read_symlink("/proc/self/exe");
#endif
#endif
#else
#if defined(__sun)
return fs::read_symlink("/proc/self/path/a.out");
#else
return fs::read_symlink("/proc/self/exe");
#endif
#endif
}
static std::regex CONDA_INITIALIZE_RE_BLOCK("# >>> mamba initialize >>>(?:\n|\r\n)?"
@ -201,17 +203,22 @@ namespace mamba
}
catch (...)
{
std::cout << termcolor::red << "ERROR: Could not find bash, or use cygpath to convert Windows path to Unix." << termcolor::reset << std::endl;
std::cout
<< termcolor::red
<< "ERROR: Could not find bash, or use cygpath to convert Windows path to Unix."
<< termcolor::reset << std::endl;
exit(1);
}
}
std::string rcfile_content(const fs::path& env_prefix, const std::string& shell, const fs::path& mamba_exe)
std::string rcfile_content(const fs::path& env_prefix,
const std::string& shell,
const fs::path& mamba_exe)
{
std::stringstream content;
// todo use get bin dir here!
#ifdef _WIN32
#ifdef _WIN32
std::string cyg_mamba_exe = native_path_to_unix(mamba_exe);
// fs::path cyg_mamba_exe = native_path_to_unix(env_prefix / 'Scripts' / 'micromamba.exe');
content << "# >>> mamba initialize >>>\n";
@ -221,7 +228,7 @@ namespace mamba
content << "# <<< mamba initialize <<<\n";
return content.str();
#else
#else
fs::path env_bin = env_prefix / "bin";
@ -229,12 +236,14 @@ namespace mamba
content << "# !! Contents within this block are managed by 'mamba init' !!\n";
content << "export MAMBA_EXE=" << mamba_exe << ";\n";
content << "export MAMBA_ROOT_PREFIX=" << env_prefix << ";\n";
content << "__mamba_setup=\"$(" << std::quoted(mamba_exe.string(), '\'') << " shell hook --shell "
<< shell << " --prefix " << std::quoted(env_prefix.string(), '\'') << " 2> /dev/null)\"\n";
content << "__mamba_setup=\"$(" << std::quoted(mamba_exe.string(), '\'')
<< " shell hook --shell " << shell << " --prefix "
<< std::quoted(env_prefix.string(), '\'') << " 2> /dev/null)\"\n";
content << "if [ $? -eq 0 ]; then\n";
content << " eval \"$__mamba_setup\"\n";
content << "else\n";
content << " if [ -f " << (env_prefix / "etc" / "profile.d" / "mamba.sh") << " ]; then\n";
content << " if [ -f " << (env_prefix / "etc" / "profile.d" / "mamba.sh")
<< " ]; then\n";
content << " . " << (env_prefix / "etc" / "profile.d" / "mamba.sh") << "\n";
content << " else\n";
content << " export PATH=\"" << env_bin.c_str() << ":$PATH\"\n";
@ -245,10 +254,12 @@ namespace mamba
return content.str();
#endif
#endif
}
std::string xonsh_content(const fs::path& env_prefix, const std::string& shell, const fs::path& mamba_exe)
std::string xonsh_content(const fs::path& env_prefix,
const std::string& shell,
const fs::path& mamba_exe)
{
std::stringstream content;
std::string s_mamba_exe;
@ -270,22 +281,29 @@ namespace mamba
content << "import sys as _sys\n";
content << "from types import ModuleType as _ModuleType\n";
content << "_mod = _ModuleType(\"xontrib.mamba\",\n";
content << " \'Autogenerated from $(" << mamba_exe << " shell hook -s xonsh -p " << env_prefix << ")\')\n";
content << "__xonsh__.execer.exec($(" << mamba_exe << " \"shell\" \"hook\" -s xonsh -p " << env_prefix << "),\n";
content << " \'Autogenerated from $(" << mamba_exe
<< " shell hook -s xonsh -p " << env_prefix << ")\')\n";
content << "__xonsh__.execer.exec($(" << mamba_exe << " \"shell\" \"hook\" -s xonsh -p "
<< env_prefix << "),\n";
content << " glbs=_mod.__dict__,\n";
content << " filename=\'$(" << mamba_exe << " shell hook -s xonsh -p " << env_prefix << ")\')\n";
content << " filename=\'$(" << mamba_exe << " shell hook -s xonsh -p "
<< env_prefix << ")\')\n";
content << "_sys.modules[\"xontrib.mamba\"] = _mod\n";
content << "del _sys, _mod, _ModuleType\n";
content << "# <<< mamba initialize <<<\n";
return content.str();
}
bool modify_rc_file(const fs::path& file_path, const fs::path& conda_prefix,
const std::string& shell, const fs::path& mamba_exe)
bool modify_rc_file(const fs::path& file_path,
const fs::path& conda_prefix,
const std::string& shell,
const fs::path& mamba_exe)
{
Console::stream() << "Modifiying RC file " << file_path
<< "\nGenerating config for root prefix " << termcolor::bold << conda_prefix << termcolor::reset
<< "\nSetting mamba executable to: " << termcolor::bold << mamba_exe << termcolor::reset;
<< "\nGenerating config for root prefix " << termcolor::bold
<< conda_prefix << termcolor::reset
<< "\nSetting mamba executable to: " << termcolor::bold << mamba_exe
<< termcolor::reset;
// TODO do we need binary or not?
std::string rc_content = read_contents(file_path, std::ios::in);
@ -300,14 +318,13 @@ namespace mamba
conda_init_content = rcfile_content(conda_prefix, shell, mamba_exe);
}
Console::stream() << "Adding (or replacing) the following in your " << file_path << " file\n"
<< termcolor::colorize << termcolor::green << conda_init_content << termcolor::reset;
Console::stream() << "Adding (or replacing) the following in your " << file_path
<< " file\n"
<< termcolor::colorize << termcolor::green << conda_init_content
<< termcolor::reset;
std::string result = std::regex_replace(
rc_content,
CONDA_INITIALIZE_RE_BLOCK,
conda_init_content
);
std::string result
= std::regex_replace(rc_content, CONDA_INITIALIZE_RE_BLOCK, conda_init_content);
if (result.find("# >>> mamba initialize >>>") == result.npos)
{
@ -327,7 +344,8 @@ namespace mamba
Context::instance().root_prefix = root_prefix;
if (fs::exists(root_prefix))
{
if (!Console::prompt("Prefix at " + root_prefix.string() + " already exists, use as root prefix?"))
if (!Console::prompt("Prefix at " + root_prefix.string()
+ " already exists, use as root prefix?"))
{
Console::print("OK, exiting.");
exit(0);
@ -357,12 +375,15 @@ namespace mamba
fs::path self_path = get_self_exe_path();
fs::create_directories(root_prefix / "condabin");
std::cout << "writing out files to condabin: " << (root_prefix / "condabin") << std::endl;
std::cout << "writing out files to condabin: " << (root_prefix / "condabin")
<< std::endl;
std::ofstream mamba_bat_f(root_prefix / "condabin" / "mamba.bat");
std::string mamba_bat_contents(mamba_bat);
replace_all(mamba_bat_contents, std::string("__MAMBA_INSERT_ROOT_PREFIX__"),
replace_all(mamba_bat_contents,
std::string("__MAMBA_INSERT_ROOT_PREFIX__"),
std::string("@SET \"MAMBA_ROOT_PREFIX=" + root_prefix.string() + "\""));
replace_all(mamba_bat_contents, std::string("__MAMBA_INSERT_MAMBA_EXE__"),
replace_all(mamba_bat_contents,
std::string("__MAMBA_INSERT_MAMBA_EXE__"),
std::string("@SET \"MAMBA_EXE=" + self_path.string() + "\""));
mamba_bat_f << mamba_bat_contents;
@ -371,7 +392,8 @@ namespace mamba
std::string hook_content = mamba_hook_bat;
std::cout << "Self exe path: " << self_path << std::endl;
replace_all(hook_content, std::string("__MAMBA_INSERT_MAMBA_EXE__"),
replace_all(hook_content,
std::string("__MAMBA_INSERT_MAMBA_EXE__"),
std::string("@SET \"MAMBA_EXE=" + self_path.string() + "\""));
std::ofstream mamba_hook_bat_f(root_prefix / "condabin" / "mamba_hook.bat");
@ -397,12 +419,15 @@ namespace mamba
out << "# !! Contents within this block are managed by 'mamba shell init' !!\n";
out << "$Env:MAMBA_ROOT_PREFIX = " << conda_prefix << "\n";
out << "$Env:MAMBA_EXE = " << self_exe << "\n";
out << "(& " << self_exe << " 'shell' 'hook' -s 'powershell' -p " << conda_prefix << ") | Out-String | Invoke-Expression\n";
out << "(& " << self_exe << " 'shell' 'hook' -s 'powershell' -p " << conda_prefix
<< ") | Out-String | Invoke-Expression\n";
out << "#endregion\n";
return out.str();
}
bool init_powershell(const fs::path& profile_path, const fs::path& conda_prefix, bool reverse=false)
bool init_powershell(const fs::path& profile_path,
const fs::path& conda_prefix,
bool reverse = false)
{
// NB: the user may not have created a profile. We need to check
// if the file exists first.
@ -415,11 +440,7 @@ namespace mamba
if (reverse)
{
profile_content = std::regex_replace(
profile_content,
CONDA_INITIALIZE_PS_RE_BLOCK,
""
);
profile_content = std::regex_replace(profile_content, CONDA_INITIALIZE_PS_RE_BLOCK, "");
}
else
{
@ -427,8 +448,10 @@ namespace mamba
std::string conda_init_content = powershell_contents(conda_prefix);
std::cout << "Adding: \n" << conda_init_content << std::endl;
Console::stream() << "Adding (or replacing) the following in your " << profile_path << " file\n"
<< termcolor::colorize << termcolor::green << conda_init_content << termcolor::reset;
Console::stream() << "Adding (or replacing) the following in your " << profile_path
<< " file\n"
<< termcolor::colorize << termcolor::green << conda_init_content
<< termcolor::reset;
if (profile_content.find("#region mamba initialize") == profile_content.npos)
{
@ -437,10 +460,7 @@ namespace mamba
else
{
profile_content = std::regex_replace(
profile_content,
CONDA_INITIALIZE_PS_RE_BLOCK,
conda_init_content
);
profile_content, CONDA_INITIALIZE_PS_RE_BLOCK, conda_init_content);
}
}
if (profile_content != profile_original_content)
@ -482,11 +502,11 @@ namespace mamba
}
else if (shell == "cmd.exe")
{
#ifndef _WIN32
#ifndef _WIN32
throw std::runtime_error("CMD.EXE can only be initialized on Windows.");
#else
#else
init_cmd_exe_registry(L"Software\\Microsoft\\Command Processor", conda_prefix, false);
#endif
#endif
}
else if (shell == "powershell")
{
@ -500,11 +520,11 @@ namespace mamba
// just ask different possible installations of PowerShell where their
// profiles are.
auto find_powershell_paths = [&profile_var](const std::string& exe) -> std::string
{
auto find_powershell_paths = [&profile_var](const std::string& exe) -> std::string {
try
{
auto obuf = subprocess::check_output({exe, "-NoProfile", "-Command", profile_var});
auto obuf
= subprocess::check_output({ exe, "-NoProfile", "-Command", profile_var });
std::string res(obuf.buf.data());
return std::string(strip(res));
}
@ -515,7 +535,7 @@ namespace mamba
};
std::string profile_path, exe;
for (auto& iter_exe : std::vector<std::string>{"powershell", "pwsh", "pwsh-preview"})
for (auto& iter_exe : std::vector<std::string>{ "powershell", "pwsh", "pwsh-preview" })
{
auto res = find_powershell_paths(iter_exe);
if (!res.empty())
@ -524,7 +544,8 @@ namespace mamba
exe = iter_exe;
}
}
std::cout << "Found powershell at " << exe << " and user profile at " << profile_path << std::endl;
std::cout << "Found powershell at " << exe << " and user profile at " << profile_path
<< std::endl;
init_powershell(profile_path, conda_prefix, false);
}

View File

@ -7,26 +7,26 @@
#ifndef MAMBA_SOLVER_HPP
#define MAMBA_SOLVER_HPP
#include <vector>
#include <utility>
#include <string>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "pool.hpp"
#include "prefix_data.hpp"
#include "match_spec.hpp"
#include "output.hpp"
#include "pool.hpp"
#include "prefix_data.hpp"
extern "C"
{
#include "solv/queue.h"
#include "solv/conda.h"
#include "solv/solver.h"
#include "solv/solverdebug.h"
#include "solv/conda.h"
#include "solv/queue.h"
#include "solv/solver.h"
#include "solv/solverdebug.h"
}
#define MAMBA_NO_DEPS 0b0001
#define MAMBA_ONLY_DEPS 0b0010
#define MAMBA_NO_DEPS 0b0001
#define MAMBA_ONLY_DEPS 0b0010
#define MAMBA_FORCE_REINSTALL 0b0100
namespace mamba
@ -34,8 +34,9 @@ namespace mamba
class MSolver
{
public:
MSolver(MPool& pool, const std::vector<std::pair<int, int>>& flags = {}, const PrefixData* = nullptr);
MSolver(MPool& pool,
const std::vector<std::pair<int, int>>& flags = {},
const PrefixData* = nullptr);
~MSolver();
MSolver(const MSolver&) = delete;
@ -62,20 +63,19 @@ namespace mamba
bool force_reinstall = false;
private:
void add_channel_specific_job(const MatchSpec& ms, int job_flag);
void add_reinstall_job(MatchSpec& ms, int job_flag);
std::vector<std::pair<int, int>> m_flags;
std::vector<MatchSpec> m_install_specs;
std::vector<MatchSpec> m_remove_specs;
std::vector<MatchSpec> m_neuter_specs; // unused for now
std::vector<MatchSpec> m_neuter_specs; // unused for now
bool m_is_solved;
Solver* m_solver;
Pool* m_pool;
Queue m_jobs;
const PrefixData* m_prefix_data = nullptr;
};
}
} // namespace mamba
#endif // MAMBA_SOLVER_HPP
#endif // MAMBA_SOLVER_HPP

View File

@ -7,17 +7,17 @@
#ifndef MAMBA_SUBDIRDATA_HPP
#define MAMBA_SUBDIRDATA_HPP
#include <string>
#include "thirdparty/filesystem.hpp"
#include <memory>
#include <regex>
#include "nlohmann/json.hpp"
#include <string>
#include "context.hpp"
#include "repo.hpp"
#include "util.hpp"
#include "fetch.hpp"
#include "nlohmann/json.hpp"
#include "output.hpp"
#include "repo.hpp"
#include "thirdparty/filesystem.hpp"
#include "util.hpp"
namespace fs = ghc::filesystem;
@ -31,11 +31,13 @@ namespace mamba
class MSubdirData
{
public:
MSubdirData(const std::string& name, const std::string& url, const std::string& repodata_fn);
MSubdirData(const std::string& name,
const std::string& url,
const std::string& repodata_fn);
// TODO return seconds as double
fs::file_time_type::duration check_cache(const fs::path& cache_file, const fs::file_time_type::clock::time_point& ref);
fs::file_time_type::duration check_cache(const fs::path& cache_file,
const fs::file_time_type::clock::time_point& ref);
bool loaded();
bool forbid_cache();
bool load();
@ -47,7 +49,6 @@ namespace mamba
MRepo create_repo(MPool& pool);
private:
bool decompress();
void create_target(nlohmann::json& mod_etag);
std::size_t get_cache_control_max_age(const std::string& val);
@ -80,6 +81,6 @@ namespace mamba
std::string cache_fn_url(const std::string& url);
std::string create_cache_dir();
}
} // namespace mamba
#endif // MAMBA_SUBDIRDATA_HPP
#endif // MAMBA_SUBDIRDATA_HPP

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -16,32 +16,28 @@
// defines the appropriate macro that is used to wrap some
// platform specific things
#if defined(_WIN32) || defined(_WIN64)
# define TERMCOLOR_OS_WINDOWS
#define TERMCOLOR_OS_WINDOWS
#elif defined(__APPLE__)
# define TERMCOLOR_OS_MACOS
#define TERMCOLOR_OS_MACOS
#elif defined(__unix__) || defined(__unix)
# define TERMCOLOR_OS_LINUX
#define TERMCOLOR_OS_LINUX
#else
# error unsupported platform
#error unsupported platform
#endif
// This headers provides the `isatty()`/`fileno()` functions,
// which are used for testing whether a standart stream refers
// to the terminal. As for Windows, we also need WinApi funcs
// for changing colors attributes of the terminal.
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
# include <unistd.h>
#include <unistd.h>
#elif defined(TERMCOLOR_OS_WINDOWS)
# include <io.h>
# include <windows.h>
#include <io.h>
#include <windows.h>
#endif
#include <iostream>
#include <cstdio>
#include <iostream>
namespace termcolor
{
@ -57,157 +53,138 @@ namespace termcolor
inline bool is_colorized(std::ostream& stream);
inline bool is_atty(const std::ostream& stream);
#if defined(TERMCOLOR_OS_WINDOWS)
inline void win_change_attributes(std::ostream& stream, int foreground, int background=-1);
#endif
}
#if defined(TERMCOLOR_OS_WINDOWS)
inline void win_change_attributes(std::ostream& stream,
int foreground,
int background = -1);
#endif
} // namespace _internal
inline
std::ostream& colorize(std::ostream& stream)
inline std::ostream& colorize(std::ostream& stream)
{
stream.iword(_internal::colorize_index) = 1L;
return stream;
}
inline
std::ostream& nocolorize(std::ostream& stream)
inline std::ostream& nocolorize(std::ostream& stream)
{
stream.iword(_internal::colorize_index) = 0L;
return stream;
}
inline
std::ostream& reset(std::ostream& stream)
inline std::ostream& reset(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[00m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1, -1);
#endif
#endif
}
return stream;
}
inline
std::ostream& bold(std::ostream& stream)
inline std::ostream& bold(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[1m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& dark(std::ostream& stream)
inline std::ostream& dark(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[2m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& italic(std::ostream& stream)
inline std::ostream& italic(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[3m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& underline(std::ostream& stream)
inline std::ostream& underline(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[4m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& blink(std::ostream& stream)
inline std::ostream& blink(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[5m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& reverse(std::ostream& stream)
inline std::ostream& reverse(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[7m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& concealed(std::ostream& stream)
inline std::ostream& concealed(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[8m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& crossed(std::ostream& stream)
inline std::ostream& crossed(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[9m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
#endif
}
return stream;
}
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
template <uint8_t code>
inline
std::ostream& color(std::ostream& stream)
inline std::ostream& color(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
@ -220,8 +197,7 @@ namespace termcolor
}
template <uint8_t code>
inline
std::ostream& on_color(std::ostream& stream)
inline std::ostream& on_color(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
@ -233,270 +209,224 @@ namespace termcolor
return stream;
}
#endif // defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#endif // defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
inline
std::ostream& grey(std::ostream& stream)
inline std::ostream& grey(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[30m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
0 // grey (black)
0 // grey (black)
);
#endif
#endif
}
return stream;
}
inline
std::ostream& red(std::ostream& stream)
inline std::ostream& red(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[31m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_RED
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, FOREGROUND_RED);
#endif
}
return stream;
}
inline
std::ostream& green(std::ostream& stream)
inline std::ostream& green(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[32m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_GREEN
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, FOREGROUND_GREEN);
#endif
}
return stream;
}
inline
std::ostream& yellow(std::ostream& stream)
inline std::ostream& yellow(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[33m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_GREEN | FOREGROUND_RED
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, FOREGROUND_GREEN | FOREGROUND_RED);
#endif
}
return stream;
}
inline
std::ostream& blue(std::ostream& stream)
inline std::ostream& blue(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[34m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_BLUE
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, FOREGROUND_BLUE);
#endif
}
return stream;
}
inline
std::ostream& magenta(std::ostream& stream)
inline std::ostream& magenta(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[35m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_BLUE | FOREGROUND_RED
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_RED);
#endif
}
return stream;
}
inline
std::ostream& cyan(std::ostream& stream)
inline std::ostream& cyan(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[36m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_BLUE | FOREGROUND_GREEN
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_GREEN);
#endif
}
return stream;
}
inline
std::ostream& white(std::ostream& stream)
inline std::ostream& white(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[37m";
#elif defined(TERMCOLOR_OS_WINDOWS)
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
);
#endif
FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
#endif
}
return stream;
}
inline
std::ostream& on_grey(std::ostream& stream)
inline std::ostream& on_grey(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[40m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
0 // grey (black)
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream,
-1,
0 // grey (black)
);
#endif
#endif
}
return stream;
}
inline
std::ostream& on_red(std::ostream& stream)
inline std::ostream& on_red(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[41m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_RED
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1, BACKGROUND_RED);
#endif
}
return stream;
}
inline
std::ostream& on_green(std::ostream& stream)
inline std::ostream& on_green(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[42m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_GREEN
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1, BACKGROUND_GREEN);
#endif
}
return stream;
}
inline
std::ostream& on_yellow(std::ostream& stream)
inline std::ostream& on_yellow(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[43m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_GREEN | BACKGROUND_RED
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1, BACKGROUND_GREEN | BACKGROUND_RED);
#endif
}
return stream;
}
inline
std::ostream& on_blue(std::ostream& stream)
inline std::ostream& on_blue(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[44m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_BLUE
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1, BACKGROUND_BLUE);
#endif
}
return stream;
}
inline
std::ostream& on_magenta(std::ostream& stream)
inline std::ostream& on_magenta(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[45m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_BLUE | BACKGROUND_RED
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1, BACKGROUND_BLUE | BACKGROUND_RED);
#endif
}
return stream;
}
inline
std::ostream& on_cyan(std::ostream& stream)
inline std::ostream& on_cyan(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[46m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_GREEN | BACKGROUND_BLUE
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1, BACKGROUND_GREEN | BACKGROUND_BLUE);
#endif
}
return stream;
}
inline
std::ostream& on_white(std::ostream& stream)
inline std::ostream& on_white(std::ostream& stream)
{
if (_internal::is_colorized(stream))
{
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
stream << "\033[47m";
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(stream, -1,
BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
);
#endif
#elif defined(TERMCOLOR_OS_WINDOWS)
_internal::win_change_attributes(
stream, -1, BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED);
#endif
}
return stream;
}
//! Since C++ hasn't a way to hide something in the header from
//! the outer access, I have to introduce this namespace which
//! is used for internal purpose and should't be access from
@ -506,8 +436,7 @@ namespace termcolor
//! Since C++ hasn't a true way to extract stream handler
//! from the a given `std::ostream` object, I have to write
//! this kind of hack.
inline
FILE* get_standard_stream(const std::ostream& stream)
inline FILE* get_standard_stream(const std::ostream& stream)
{
if (&stream == &std::cout)
return stdout;
@ -520,16 +449,14 @@ namespace termcolor
// Say whether a given stream should be colorized or not. It's always
// true for ATTY streams and may be true for streams marked with
// colorize flag.
inline
bool is_colorized(std::ostream& stream)
inline bool is_colorized(std::ostream& stream)
{
return is_atty(stream) || static_cast<bool>(stream.iword(colorize_index));
}
//! Test whether a given `std::ostream` object refers to
//! a terminal.
inline
bool is_atty(const std::ostream& stream)
inline bool is_atty(const std::ostream& stream)
{
FILE* std_stream = get_standard_stream(stream);
@ -540,14 +467,14 @@ namespace termcolor
if (!std_stream)
return false;
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
return ::isatty(fileno(std_stream));
#elif defined(TERMCOLOR_OS_WINDOWS)
#elif defined(TERMCOLOR_OS_WINDOWS)
return ::_isatty(_fileno(std_stream));
#endif
#endif
}
#if defined(TERMCOLOR_OS_WINDOWS)
#if defined(TERMCOLOR_OS_WINDOWS)
//! Change Windows Terminal colors attribute. If some
//! parameter is `-1` then attribute won't changed.
inline void win_change_attributes(std::ostream& stream, int foreground, int background)
@ -604,15 +531,14 @@ namespace termcolor
SetConsoleTextAttribute(hTerminal, info.wAttributes);
}
#endif // TERMCOLOR_OS_WINDOWS
#endif // TERMCOLOR_OS_WINDOWS
} // namespace _internal
} // namespace termcolor
} // namespace _internal
} // namespace termcolor
#undef TERMCOLOR_OS_WINDOWS
#undef TERMCOLOR_OS_MACOS
#undef TERMCOLOR_OS_LINUX
#endif // TERMCOLOR_HPP_
#endif // TERMCOLOR_HPP_

View File

@ -14,10 +14,10 @@
#include <functional>
#include <mutex>
#include <thread>
#include <utility>
namespace mamba
{
#ifdef MAMBA_TEST_SUITE
#endif
@ -35,7 +35,6 @@ namespace mamba
class thread_interrupted : public std::exception
{
public:
thread_interrupted() = default;
};
@ -72,7 +71,6 @@ namespace mamba
class thread
{
public:
thread() = default;
~thread() = default;
@ -92,7 +90,6 @@ namespace mamba
void detach();
private:
std::thread m_thread;
};
@ -100,14 +97,13 @@ namespace mamba
inline thread::thread(Function&& func, Args&&... args)
{
auto f = std::bind(std::forward<Function>(func), std::forward<Args>(args)...);
m_thread = std::thread([f]()
{
m_thread = std::thread([f]() {
increase_thread_count();
try
{
f();
}
catch(thread_interrupted&)
catch (thread_interrupted&)
{
}
decrease_thread_count();
@ -121,7 +117,6 @@ namespace mamba
class interruption_guard
{
public:
template <class Function, class... Args>
interruption_guard(Function&& func, Args&&... args);
~interruption_guard();
@ -133,9 +128,8 @@ namespace mamba
interruption_guard& operator=(interruption_guard&&) = delete;
private:
#ifdef _WIN32
static std::function<void ()> m_cleanup_function;
static std::function<void()> m_cleanup_function;
#else
void block_signals() const;
void wait_for_signal() const;
@ -164,8 +158,7 @@ namespace mamba
{
block_signals();
auto f = std::bind(std::forward<Function>(func), std::forward<Args>(args)...);
std::thread victor_the_cleaner([f, this]()
{
std::thread victor_the_cleaner([f, this]() {
wait_for_signal();
if (m_interrupt.load())
{
@ -177,10 +170,10 @@ namespace mamba
});
register_cleaning_thread_id(victor_the_cleaner.native_handle());
victor_the_cleaner.detach();
};
}
#endif
}
} // namespace mamba
#endif

View File

@ -7,25 +7,27 @@
#ifndef MAMBA_TRANSACTION_HPP
#define MAMBA_TRANSACTION_HPP
#include <iomanip>
#include <set>
#include <future>
#include <iomanip>
#include <memory>
#include <set>
#include <string>
#include <tuple>
#include <vector>
#include "nlohmann/json.hpp"
#include "thirdparty/filesystem.hpp"
#include "repo.hpp"
#include "fetch.hpp"
#include "package_handling.hpp"
#include "package_cache.hpp"
#include "nlohmann/json.hpp"
#include "output.hpp"
#include "package_cache.hpp"
#include "package_handling.hpp"
#include "prefix_data.hpp"
#include "repo.hpp"
#include "thirdparty/filesystem.hpp"
#include "transaction_context.hpp"
extern "C"
{
#include "solv/transaction.h"
#include "solv/transaction.h"
}
#include "solver.hpp"
@ -40,7 +42,6 @@ namespace mamba
class PackageDownloadExtractTarget
{
public:
PackageDownloadExtractTarget(const MRepo& repo, Solvable* solvable);
void write_repodata_record(const fs::path& base_path);
@ -51,7 +52,6 @@ namespace mamba
DownloadTarget* target(const fs::path& cache_path, MultiPackageCache& cache);
private:
Solvable* m_solv;
ProgressProxy m_progress_proxy;
@ -69,8 +69,8 @@ namespace mamba
class MTransaction
{
public:
enum class FilterType {
enum class FilterType
{
none,
keep_only,
ignore
@ -102,7 +102,6 @@ namespace mamba
std::string find_python_version();
private:
FilterType m_filter_type = FilterType::none;
std::set<Id> m_filter_name_ids;
@ -114,6 +113,6 @@ namespace mamba
bool m_force_reinstall = false;
};
}
} // namespace mamba
#endif // MAMBA_TRANSACTION_HPP
#endif // MAMBA_TRANSACTION_HPP

View File

@ -20,22 +20,22 @@ namespace mamba
fs::path get_python_short_path(const std::string& python_version);
fs::path get_python_site_packages_short_path(const std::string& python_version);
fs::path get_bin_directory_short_path();
fs::path get_python_noarch_target_path(const std::string& source_short_path, const fs::path& target_site_packages_short_path);
fs::path get_python_noarch_target_path(const std::string& source_short_path,
const fs::path& target_site_packages_short_path);
class TransactionContext
{
public:
TransactionContext() = default;
TransactionContext(const fs::path& prefix, const std::string& py_version);
TransactionContext() = default;
TransactionContext(const fs::path& prefix, const std::string& py_version);
bool has_python;
fs::path target_prefix;
fs::path site_packages_path;
fs::path python_path;
std::string python_version;
std::string short_python_version;
bool has_python;
fs::path target_prefix;
fs::path site_packages_path;
fs::path python_path;
std::string python_version;
std::string short_python_version;
};
}
} // namespace mamba
#endif

View File

@ -7,15 +7,16 @@
#ifndef MAMBA_URL_HPP
#define MAMBA_URL_HPP
#include <string>
#include <stdexcept>
#include <vector>
extern "C"
{
#include <curl/curl.h>
#include <curl/curl.h>
}
#include <limits>
#include <stdexcept>
#include <string>
#include <vector>
// typedef enum {
// CURLUE_OK,
// CURLUE_BAD_HANDLE, /* 1 */
@ -41,9 +42,7 @@ namespace mamba
{
bool has_scheme(const std::string& url);
void split_anaconda_token(const std::string& url,
std::string& cleaned_url,
std::string& token);
void split_anaconda_token(const std::string& url, std::string& cleaned_url, std::string& token);
void split_scheme_auth_token(const std::string& url,
std::string& remaining_url,
@ -65,7 +64,6 @@ namespace mamba
class URLHandler
{
public:
URLHandler(const std::string& url = "");
~URLHandler();
@ -105,7 +103,6 @@ namespace mamba
URLHandler& set_zoneid(const std::string& zoneid);
private:
std::string get_part(CURLUPart part);
void set_part(CURLUPart part, const std::string& s);
@ -138,7 +135,7 @@ namespace mamba
s1 += s2;
return join_url_impl(s1, args...);
}
}
} // namespace detail
inline std::string join_url()
{
@ -151,6 +148,6 @@ namespace mamba
std::string res = s;
return detail::join_url_impl(res, args...);
}
}
} // namespace mamba
#endif

View File

@ -9,11 +9,13 @@
#include <array>
#include <iomanip>
#include <limits>
#include <random>
#include <sstream>
#include <stdexcept>
#include <string_view>
#include <string>
#include <string_view>
#include <vector>
#include "nlohmann/json.hpp"
#include "thirdparty/filesystem.hpp"
@ -22,26 +24,25 @@ namespace fs = ghc::filesystem;
namespace mamba
{
#if __APPLE__ || __MACH__
#if __APPLE__ || __MACH__
static constexpr bool on_win = false;
static constexpr bool on_linux = false;
static constexpr bool on_mac = true;
#elif __linux__
#elif __linux__
static constexpr bool on_win = false;
static constexpr bool on_linux = true;
static constexpr bool on_mac = false;
#elif _WIN32
#elif _WIN32
static constexpr bool on_win = true;
static constexpr bool on_linux = false;
static constexpr bool on_mac = false;
#else
#error "no supported OS detected"
#endif
#else
#error "no supported OS detected"
#endif
class mamba_error : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};
@ -52,35 +53,38 @@ namespace mamba
std::vector<fs::path> filter_dir(const fs::path& dir, const std::string& suffix);
bool paths_equal(const fs::path& lhs, const fs::path& rhs);
std::string read_contents(const fs::path& path, std::ios::openmode mode = std::ios::in | std::ios::binary);
std::string read_contents(const fs::path& path,
std::ios::openmode mode = std::ios::in | std::ios::binary);
std::vector<std::string> read_lines(const fs::path& path);
inline void make_executable(const fs::path& p)
{
fs::permissions(p, fs::perms::owner_all | fs::perms::group_all | fs::perms::others_read | fs::perms::others_exec);
fs::permissions(p,
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_read
| fs::perms::others_exec);
}
template <typename T = std::mt19937>
inline auto random_generator() -> T
{
auto constexpr seed_bits = sizeof(typename T::result_type) * T::state_size;
auto constexpr seed_len = seed_bits / std::numeric_limits<std::seed_seq::result_type>::digits;
auto constexpr seed_len
= seed_bits / std::numeric_limits<std::seed_seq::result_type>::digits;
auto seed = std::array<std::seed_seq::result_type, seed_len>{};
auto dev = std::random_device{};
std::generate_n(begin(seed), seed_len, std::ref(dev));
auto seed_seq = std::seed_seq(begin(seed), end(seed));
return T{seed_seq};
return T{ seed_seq };
}
inline std::string generate_random_alphanumeric_string(std::size_t len)
{
static constexpr auto chars =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
static constexpr auto chars = "0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
thread_local auto rng = random_generator<std::mt19937>();
auto dist = std::uniform_int_distribution{{}, std::strlen(chars)};
auto dist = std::uniform_int_distribution{ {}, std::strlen(chars) };
auto result = std::string(len, '\0');
std::generate_n(begin(result), len, [&]() { return chars[dist(rng)]; });
return result;
@ -89,7 +93,6 @@ namespace mamba
class TemporaryDirectory
{
public:
TemporaryDirectory();
~TemporaryDirectory();
@ -101,14 +104,12 @@ namespace mamba
operator fs::path();
private:
fs::path m_path;
};
class TemporaryFile
{
public:
TemporaryFile(const std::string& prefix = "mambaf", const std::string& suffix = "");
~TemporaryFile();
@ -120,7 +121,6 @@ namespace mamba
operator fs::path();
private:
fs::path m_path;
};
@ -157,7 +157,8 @@ namespace mamba
template <class S>
inline std::string join(const char* j, const S& container)
{
if (container.empty()) return "";
if (container.empty())
return "";
std::string result = container[0];
for (std::size_t i = 1; i < container.size(); ++i)
{
@ -167,13 +168,9 @@ namespace mamba
return result;
}
void replace_all(std::string& data,
const std::string& search,
const std::string& replace);
void replace_all(std::string& data, const std::string& search, const std::string& replace);
void replace_all(std::wstring& data,
const std::wstring& search,
const std::wstring& replace);
void replace_all(std::wstring& data, const std::wstring& search, const std::wstring& replace);
// Note: this function only works for non-unicode!
std::string to_upper(const std::string_view& input);
@ -198,26 +195,30 @@ namespace mamba
{
inline sizer(const char* s)
: size(strlen(s))
{}
{
}
inline sizer(const char s)
: size(1)
{}
{
}
template <class T>
inline sizer(T& s)
: size(s.size())
{}
{
}
std::size_t size;
};
}
} // namespace concat_impl
template<typename... Args>
template <typename... Args>
inline std::string concat(const Args&... args)
{
size_t len = 0;
for (auto s : std::initializer_list<concat_impl::sizer>{args...}) len += s.size;
for (auto s : std::initializer_list<concat_impl::sizer>{ args... })
len += s.size;
std::string result;
result.reserve(len);
@ -247,6 +248,6 @@ namespace mamba
else
target = default_value;
}
}
} // namespace mamba
#endif // MAMBA_UTIL_HPP
#endif // MAMBA_UTIL_HPP

View File

@ -7,6 +7,8 @@
#ifndef MAMBA_VALIDATE_HPP
#define MAMBA_VALIDATE_HPP
#include <string>
#include "thirdparty/filesystem.hpp"
namespace fs = ghc::filesystem;
@ -18,6 +20,6 @@ namespace validate
bool sha256(const std::string& path, const std::string& validation);
bool md5(const std::string& path, const std::string& validation);
bool file_size(const fs::path& path, std::uintmax_t validation);
}
} // namespace validate
#endif //MAMBA_VALIDATE_HPP
#endif // MAMBA_VALIDATE_HPP

View File

@ -5,6 +5,7 @@
// The full license is in the file LICENSE, distributed with this software.
#include "activation.hpp"
#include "environment.hpp"
namespace mamba
@ -13,8 +14,8 @@ namespace mamba
{
fs::path PREFIX_STATE_FILE = fs::path("conda-meta") / "state";
fs::path PACKAGE_ENV_VARS_DIR = fs::path("etc") / "conda" / "env_vars.d";
std::string CONDA_ENV_VARS_UNSET_VAR = "***unset***";
}
std::string CONDA_ENV_VARS_UNSET_VAR = "***unset***"; // NOLINT(runtime/string)
} // namespace
/****************************
* Activator implementation *
@ -59,7 +60,8 @@ namespace mamba
}
}
std::vector<std::pair<std::string, std::string>> Activator::get_environment_vars(const fs::path& prefix)
std::vector<std::pair<std::string, std::string>> Activator::get_environment_vars(
const fs::path& prefix)
{
fs::path env_vars_file = prefix / PREFIX_STATE_FILE;
fs::path pkg_env_var_dir = prefix / PACKAGE_ENV_VARS_DIR;
@ -74,7 +76,8 @@ namespace mamba
// if exists(pkg_env_var_dir):
// for pkg_env_var_file in sorted(os.listdir(pkg_env_var_dir)):
// with open(join(pkg_env_var_dir, pkg_env_var_file), 'r') as f:
// env_vars.update(json.loads(f.read(), object_pairs_hook=OrderedDict))
// env_vars.update(json.loads(f.read(),
object_pairs_hook=OrderedDict))
}*/
// Then get env vars from environment specification
@ -84,9 +87,10 @@ namespace mamba
// with open(env_vars_file, 'r') as f:
// prefix_state = json.loads(f.read(), object_pairs_hook=OrderedDict)
// prefix_state_env_vars = prefix_state.get('env_vars', {})
// dup_vars = [ev for ev in env_vars.keys() if ev in prefix_state_env_vars.keys()]
// for dup in dup_vars:
// print("WARNING: duplicate env vars detected. Vars from the environment "
// dup_vars = [ev for ev in env_vars.keys() if ev in
// prefix_state_env_vars.keys()] for dup in dup_vars:
// print("WARNING: duplicate env vars detected. Vars from the
// environment "
// "will overwrite those from packages", file=sys.stderr)
// print("variable %s duplicated" % dup, file=sys.stderr)
// env_vars.update(prefix_state_env_vars)
@ -105,8 +109,10 @@ namespace mamba
std::string env_i;
for (int i = 1; i < old_conda_shlvl + 1; ++i)
{
std::string env_prefix = (i == old_conda_shlvl) ? "CONDA_PREFIX" : "CONDA_PREFIX_" + std::to_string(i);
std::string prefix = (m_env.find(env_prefix) != m_env.end()) ? m_env[env_prefix] : "";
std::string env_prefix
= (i == old_conda_shlvl) ? "CONDA_PREFIX" : "CONDA_PREFIX_" + std::to_string(i);
std::string prefix
= (m_env.find(env_prefix) != m_env.end()) ? m_env[env_prefix] : "";
env_i = get_default_env(prefix);
bool stacked_i = m_env.find("CONDA_STACKED_" + std::to_string(i)) != m_env.end();
@ -126,7 +132,8 @@ namespace mamba
prompt_stack.pop_back();
if (env_stack.size())
env_stack.pop_back();
bool stacked = m_env.find("CONDA_STACKED_" + std::to_string(old_conda_shlvl)) != m_env.end();
bool stacked
= m_env.find("CONDA_STACKED_" + std::to_string(old_conda_shlvl)) != m_env.end();
if (!stacked && env_stack.size())
{
prompt_stack.push_back(env_stack.back());
@ -166,13 +173,11 @@ namespace mamba
{
if (on_win)
{
return {
prefix / "Library" / "mingw-w64" / "bin",
prefix / "Library" / "usr" / "bin",
prefix / "Library" / "bin",
prefix / "Scripts",
prefix / "bin"
};
return { prefix / "Library" / "mingw-w64" / "bin",
prefix / "Library" / "usr" / "bin",
prefix / "Library" / "bin",
prefix / "Scripts",
prefix / "bin" };
}
else
{
@ -183,13 +188,13 @@ namespace mamba
std::vector<fs::path> Activator::get_clean_dirs()
{
// For isolation, running the conda test suite *without* env. var. inheritance
// every so often is a good idea. We should probably make this a pytest fixture
// along with one that tests both hardlink-only and copy-only, but before that
// conda's testsuite needs to be a lot faster!
// clean_paths = {'darwin': '/usr/bin:/bin:/usr/sbin:/sbin',
// # You may think 'let us do something more clever here and interpolate
// # `%windir%`' but the point here is the the whole env. is cleaned out
// 'win32': 'C:\\Windows\\system32;'
// every so often is a good idea. We should probably make this a pytest
// fixture along with one that tests both hardlink-only and copy-only, but
// before that conda's testsuite needs to be a lot faster! clean_paths =
// {'darwin': '/usr/bin:/bin:/usr/sbin:/sbin',
// # You may think 'let us do something more clever here and
// interpolate # `%windir%`' but the point here is the the
// whole env. is cleaned out 'win32': 'C:\\Windows\\system32;'
// 'C:\\Windows;'
// 'C:\\Windows\\System32\\Wbem;'
// 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\'
@ -207,26 +212,25 @@ namespace mamba
{
if (on_linux)
{
path = {"/usr/bin"};
path = { "/usr/bin" };
}
else if (on_mac)
{
path = {"/usr/bin", "/bin", "/usr/sbin", "/sbin"};
path = { "/usr/bin", "/bin", "/usr/sbin", "/sbin" };
}
else
{
path = {
"C:\\Windows\\system32",
"C:\\Windows",
"C:\\Windows\\System32\\Wbem",
"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\"
};
path = { "C:\\Windows\\system32",
"C:\\Windows",
"C:\\Windows\\System32\\Wbem",
"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\" };
}
}
// We used to prepend sys.prefix\Library\bin to PATH on startup but not anymore.
// Instead, in conda 4.6 we add the full suite of entries. This is performed in
// condabin\conda.bat and condabin\ _conda_activate.bat. However, we
// need to ignore the stuff we add there, and only consider actual PATH entries.
// We used to prepend sys.prefix\Library\bin to PATH on startup but not
// anymore. Instead, in conda 4.6 we add the full suite of entries. This is
// performed in condabin\conda.bat and condabin\ _conda_activate.bat. However,
// we need to ignore the stuff we add there, and only consider actual PATH
// entries.
// prefix_dirs = tuple(self._get_path_dirs(sys.prefix))
// start_index = 0
@ -249,15 +253,16 @@ namespace mamba
// prefix = self.path_conversion(prefix)
// path_list = list(self.path_conversion(self._get_starting_path_list()))
auto path_list = get_clean_dirs();
// If this is the first time we're activating an environment, we need to ensure that
// the condabin directory is included in the path list.
// Under normal conditions, if the shell hook is working correctly, this should
// If this is the first time we're activating an environment, we need to
// ensure that the condabin directory is included in the path list. Under
// normal conditions, if the shell hook is working correctly, this should
// never trigger.
if (old_conda_shlvl == 0)
{
bool no_condabin = std::none_of(path_list.begin(), path_list.end(),
[](const std::string& s) { return ends_with(s, "condabin");}
);
bool no_condabin
= std::none_of(path_list.begin(), path_list.end(), [](const std::string& s) {
return ends_with(s, "condabin");
});
if (no_condabin)
{
auto condabin_dir = Context::instance().conda_prefix / "condabin";
@ -275,7 +280,8 @@ namespace mamba
return result;
}
std::string Activator::replace_prefix_in_path(const fs::path& old_prefix, const fs::path& new_prefix)
std::string Activator::replace_prefix_in_path(const fs::path& old_prefix,
const fs::path& new_prefix)
{
// TODO not done yet.
std::vector<fs::path> current_path = get_clean_dirs();
@ -284,12 +290,15 @@ namespace mamba
std::vector<fs::path> old_prefix_dirs = get_path_dirs(old_prefix);
// remove all old paths
current_path.erase(std::remove_if(current_path.begin(), current_path.end(), [&](const fs::path& path_elem) {
return std::find_if(old_prefix_dirs.begin(), old_prefix_dirs.end(),
[&path_elem](const fs::path& old_dir) {
return paths_equal(old_dir, path_elem);
}) != old_prefix_dirs.end();
}));
current_path.erase(std::remove_if(
current_path.begin(), current_path.end(), [&](const fs::path& path_elem) {
return std::find_if(old_prefix_dirs.begin(),
old_prefix_dirs.end(),
[&path_elem](const fs::path& old_dir) {
return paths_equal(old_dir, path_elem);
})
!= old_prefix_dirs.end();
}));
// TODO remove `sys.prefix\Library\bin` on Windows?!
// Not sure if necessary as we don't fiddle with Python
@ -306,7 +315,8 @@ namespace mamba
}
else
{
current_path.erase(std::unique(current_path.begin(), current_path.end()), current_path.end());
current_path.erase(std::unique(current_path.begin(), current_path.end()),
current_path.end());
std::string result = join(env::pathsep(), current_path);
return result;
}
@ -317,8 +327,9 @@ namespace mamba
return replace_prefix_in_path(prefix, fs::path());
}
void Activator::get_export_unset_vars(EnvironmentTransform& envt,
const std::vector<std::pair<std::string, std::string>>& to_export)
void Activator::get_export_unset_vars(
EnvironmentTransform& envt,
const std::vector<std::pair<std::string, std::string>>& to_export)
{
// conda_exe_vars_export = OrderedDict()
// for k, v in context.conda_exe_vars_dict.items():
@ -335,7 +346,7 @@ namespace mamba
}
else
{
envt.export_vars.push_back({to_upper(k), v});
envt.export_vars.push_back({ to_upper(k), v });
}
}
}
@ -360,12 +371,14 @@ namespace mamba
return envt;
}
std::string conda_default_env = (m_env.find("CONDA_DEFAULT_ENV") != m_env.end()) ?
m_env["CONDA_DEFAULT_ENV"] : get_default_env(conda_prefix);
std::string conda_default_env = (m_env.find("CONDA_DEFAULT_ENV") != m_env.end())
? m_env["CONDA_DEFAULT_ENV"]
: get_default_env(conda_prefix);
auto new_path = replace_prefix_in_path(conda_prefix, conda_prefix);
std::string conda_prompt_modifier = get_prompt_modifier(conda_prefix, conda_default_env, conda_shlvl);
std::string conda_prompt_modifier
= get_prompt_modifier(conda_prefix, conda_default_env, conda_shlvl);
if (Context::instance().change_ps1)
{
auto res = update_prompt(conda_prompt_modifier);
@ -375,17 +388,17 @@ namespace mamba
}
}
std::vector<std::pair<std::string, std::string>> env_vars_to_export = {
{"path", new_path},
{"conda_shlvl", std::to_string(conda_shlvl)},
{"conda_prompt_modifier", conda_prompt_modifier}
};
std::vector<std::pair<std::string, std::string>> env_vars_to_export
= { { "path", new_path },
{ "conda_shlvl", std::to_string(conda_shlvl) },
{ "conda_prompt_modifier", conda_prompt_modifier } };
get_export_unset_vars(envt, env_vars_to_export);
// TODO figure out if this is all really necessary?
// # environment variables are set only to aid transition from conda 4.3 to conda 4.4
// conda_environment_env_vars = self._get_environment_env_vars(conda_prefix)
// for k, v in conda_environment_env_vars.items():
// # environment variables are set only to aid transition from conda 4.3 to
// conda 4.4 conda_environment_env_vars =
// self._get_environment_env_vars(conda_prefix) for k, v in
// conda_environment_env_vars.items():
// if v == CONDA_ENV_VARS_UNSET_VAR:
// env_vars_to_unset = env_vars_to_unset + (k,)
// else:
@ -401,8 +414,7 @@ namespace mamba
{
EnvironmentTransform envt;
if (m_env.find("CONDA_PREFIX") == m_env.end() ||
m_env.find("CONDA_SHLVL") == m_env.end())
if (m_env.find("CONDA_PREFIX") == m_env.end() || m_env.find("CONDA_SHLVL") == m_env.end())
{
// nothing to deactivate
return envt;
@ -414,35 +426,36 @@ namespace mamba
int new_conda_shlvl = old_conda_shlvl - 1;
std::string conda_prompt_modifier = "";
// set_vars = {};
if (old_conda_shlvl == 1)
{
std::string new_path = remove_prefix_from_path(old_conda_prefix);
// You might think that you can remove the CONDA_EXE vars by passing conda_exe_vars=None
// here so that "deactivate means deactivate" but you cannot since the conda shell
// scripts still refer to them and they only set them once at the top. We could change
// that though, the conda() shell function could set them instead of doing it at the
// top. This would be *much* cleaner. I personally cannot abide that I have
// deactivated conda and anything at all in my env still references it (apart from the
// shell script, we need something I suppose!)
// You might think that you can remove the CONDA_EXE vars by passing
// conda_exe_vars=None here so that "deactivate means deactivate" but you
// cannot since the conda shell scripts still refer to them and they only
// set them once at the top. We could change that though, the conda() shell
// function could set them instead of doing it at the top. This would be
// *much* cleaner. I personally cannot abide that I have deactivated conda
// and anything at all in my env still references it (apart from the shell
// script, we need something I suppose!)
envt.export_path = new_path;
std::vector<std::pair<std::string, std::string>> env_vars_to_export = {
{"conda_prefix", ""},
{"conda_shlvl", std::to_string(new_conda_shlvl)},
{"conda_default_env", ""},
{"conda_prompt_modifier", ""}
};
std::vector<std::pair<std::string, std::string>> env_vars_to_export
= { { "conda_prefix", "" },
{ "conda_shlvl", std::to_string(new_conda_shlvl) },
{ "conda_default_env", "" },
{ "conda_prompt_modifier", "" } };
get_export_unset_vars(envt, env_vars_to_export);
}
else
{
assert (old_conda_shlvl > 1);
assert(old_conda_shlvl > 1);
std::string new_prefix = m_env.at("CONDA_PREFIX_" + std::to_string(new_conda_shlvl));
std::string conda_default_env = get_default_env(new_prefix);
std::string conda_prompt_modifier = get_prompt_modifier(new_prefix, conda_default_env, old_conda_shlvl);
conda_prompt_modifier
= get_prompt_modifier(new_prefix, conda_default_env, old_conda_shlvl);
auto new_conda_environment_env_vars = get_environment_vars(new_prefix);
bool old_prefix_stacked = (m_env.find("CONDA_STACKED_" + std::to_string(old_conda_shlvl)) != m_env.end());
bool old_prefix_stacked
= (m_env.find("CONDA_STACKED_" + std::to_string(old_conda_shlvl)) != m_env.end());
std::string new_path;
envt.unset_vars.push_back("CONDA_PREFIX_" + std::to_string(new_conda_shlvl));
@ -456,18 +469,17 @@ namespace mamba
new_path = replace_prefix_in_path(old_conda_prefix, new_prefix);
}
std::vector<std::pair<std::string, std::string>> env_vars_to_export = {
{"conda_prefix", "new_prefix"},
{"conda_shlvl", std::to_string(new_conda_shlvl)},
{"conda_default_env", conda_default_env},
{"conda_prompt_modifier", conda_prompt_modifier}
};
std::vector<std::pair<std::string, std::string>> env_vars_to_export
= { { "conda_prefix", "new_prefix" },
{ "conda_shlvl", std::to_string(new_conda_shlvl) },
{ "conda_default_env", conda_default_env },
{ "conda_prompt_modifier", conda_prompt_modifier } };
get_export_unset_vars(envt, env_vars_to_export);
for (auto& [k, v] : new_conda_environment_env_vars)
{
envt.export_vars.push_back({k, v});
envt.export_vars.push_back({ k, v });
}
envt.export_path = new_path;
@ -486,10 +498,11 @@ namespace mamba
for (auto& env_var : old_conda_environment_env_vars)
{
envt.unset_vars.push_back(env_var.first);
std::string save_var = std::string("__CONDA_SHLVL_") + std::to_string(new_conda_shlvl) + "_" + env_var.first; // % (new_conda_shlvl, env_var)
std::string save_var = std::string("__CONDA_SHLVL_") + std::to_string(new_conda_shlvl)
+ "_" + env_var.first; // % (new_conda_shlvl, env_var)
if (m_env.find(save_var) != m_env.end())
{
envt.export_vars.push_back({env_var.first, m_env[save_var]});
envt.export_vars.push_back({ env_var.first, m_env[save_var] });
}
}
return envt;
@ -530,9 +543,9 @@ namespace mamba
return build_reactivate();
}
if (old_conda_shlvl &&
m_env.find("CONDA_PREFIX_" + std::to_string(old_conda_shlvl - 1)) != m_env.end() &&
m_env["CONDA_PREFIX_" + std::to_string(old_conda_shlvl - 1)] == prefix)
if (old_conda_shlvl
&& m_env.find("CONDA_PREFIX_" + std::to_string(old_conda_shlvl - 1)) != m_env.end()
&& m_env["CONDA_PREFIX_" + std::to_string(old_conda_shlvl - 1)] == prefix)
{
// in this case, user is attempting to activate the previous environment,
// i.e. step back down
@ -541,7 +554,8 @@ namespace mamba
envt.activate_scripts = get_activate_scripts(prefix);
std::string conda_default_env = get_default_env(prefix);
std::string conda_prompt_modifier = get_prompt_modifier(prefix, conda_default_env, old_conda_shlvl);
std::string conda_prompt_modifier
= get_prompt_modifier(prefix, conda_default_env, old_conda_shlvl);
auto conda_environment_env_vars = get_environment_vars(prefix);
@ -553,7 +567,8 @@ namespace mamba
std::vector<std::string> clobbering_env_vars;
for (auto& env_var : conda_environment_env_vars)
{
if (m_env.find(env_var.first) != m_env.end()) clobbering_env_vars.push_back(env_var.first);
if (m_env.find(env_var.first) != m_env.end())
clobbering_env_vars.push_back(env_var.first);
}
for (const auto& v : clobbering_env_vars)
@ -561,7 +576,7 @@ namespace mamba
// TODO use concat
std::stringstream tmp;
tmp << "__CONDA_SHLVL_" << old_conda_shlvl << "_" << v;
conda_environment_env_vars.push_back({tmp.str(), m_env[v]});
conda_environment_env_vars.push_back({ tmp.str(), m_env[v] });
}
if (clobbering_env_vars.size())
@ -575,17 +590,15 @@ namespace mamba
std::string new_path = add_prefix_to_path(prefix, old_conda_shlvl);
env_vars_to_export = {
{"path", std::string(new_path)},
{"conda_prefix", std::string(prefix)},
{"conda_shlvl", std::to_string(new_conda_shlvl)},
{"conda_default_env", conda_default_env},
{"conda_prompt_modifier", conda_prompt_modifier}
};
env_vars_to_export = { { "path", std::string(new_path) },
{ "conda_prefix", std::string(prefix) },
{ "conda_shlvl", std::to_string(new_conda_shlvl) },
{ "conda_default_env", conda_default_env },
{ "conda_prompt_modifier", conda_prompt_modifier } };
for (auto& [k, v] : conda_environment_env_vars)
{
envt.export_vars.push_back({k, v});
envt.export_vars.push_back({ k, v });
}
if (old_conda_shlvl == 0)
@ -597,16 +610,19 @@ namespace mamba
if (m_stack)
{
get_export_unset_vars(envt, env_vars_to_export);
envt.export_vars.push_back({"CONDA_PREFIX_" + std::to_string(old_conda_shlvl), old_conda_prefix});
envt.export_vars.push_back({"CONDA_STACKED_" + std::to_string(new_conda_shlvl), "true"});
envt.export_vars.push_back(
{ "CONDA_PREFIX_" + std::to_string(old_conda_shlvl), old_conda_prefix });
envt.export_vars.push_back(
{ "CONDA_STACKED_" + std::to_string(new_conda_shlvl), "true" });
}
else
{
new_path = replace_prefix_in_path(old_conda_prefix, prefix);
envt.deactivate_scripts = get_deactivate_scripts(old_conda_prefix);
env_vars_to_export[0] = {"PATH", new_path};
get_export_unset_vars(envt, env_vars_to_export);
envt.export_vars.push_back({"CONDA_PREFIX_" + std::to_string(old_conda_shlvl), old_conda_prefix});
env_vars_to_export[0] = { "PATH", new_path };
get_export_unset_vars(envt, env_vars_to_export);
envt.export_vars.push_back(
{ "CONDA_PREFIX_" + std::to_string(old_conda_shlvl), old_conda_prefix });
}
}
@ -698,25 +714,26 @@ namespace mamba
return out.str();
}
std::pair<std::string, std::string>
PosixActivator::update_prompt(const std::string& conda_prompt_modifier)
std::pair<std::string, std::string> PosixActivator::update_prompt(
const std::string& conda_prompt_modifier)
{
std::string ps1 = (m_env.find("PS1") != m_env.end()) ? m_env["PS1"] : "";
if (ps1.find("POWERLINE_COMMAND") != ps1.npos)
{
// Defer to powerline (https://github.com/powerline/powerline) if it's in use.
return {"", ""};
// Defer to powerline (https://github.com/powerline/powerline) if it's in
// use.
return { "", "" };
}
std::string current_prompt_modifier = env::get("CONDA_PROMPT_MODIFIER");
if (!current_prompt_modifier.empty())
{
replace_all(ps1, current_prompt_modifier, "");
}
// Because we're using single-quotes to set shell variables, we need to handle the
// proper escaping of single quotes that are already part of the string.
// Because we're using single-quotes to set shell variables, we need to handle
// the proper escaping of single quotes that are already part of the string.
// Best solution appears to be https://stackoverflow.com/a/1250279
replace_all(ps1, "'", "'\"'\"'");
return {"PS1", conda_prompt_modifier + ps1};
return { "PS1", conda_prompt_modifier + ps1 };
}
std::string PosixActivator::shell_extension()
@ -774,9 +791,10 @@ namespace mamba
return "";
}
std::pair<std::string, std::string> CmdExeActivator::update_prompt(const std::string& conda_prompt_modifier)
std::pair<std::string, std::string> CmdExeActivator::update_prompt(
const std::string& conda_prompt_modifier)
{
return {"", ""};
return { "", "" };
}
std::string CmdExeActivator::script(const EnvironmentTransform& env_transform)
@ -816,7 +834,8 @@ namespace mamba
std::ofstream out_file(tempfile_ptr->path());
out_file << out.str();
// note: we do not delete the tempfile ptr intentionally, so that the temp file stays
// note: we do not delete the tempfile ptr intentionally, so that the temp
// file stays
return tempfile_ptr->path().string();
}
@ -844,9 +863,10 @@ namespace mamba
return Context::instance().root_prefix / "condabin" / "mamba_hook.ps1";
}
std::pair<std::string, std::string> PowerShellActivator::update_prompt(const std::string& conda_prompt_modifier)
std::pair<std::string, std::string> PowerShellActivator::update_prompt(
const std::string& conda_prompt_modifier)
{
return {"", ""};
return { "", "" };
}
std::string PowerShellActivator::script(const EnvironmentTransform& env_transform)
@ -906,9 +926,10 @@ namespace mamba
return Context::instance().root_prefix / "etc" / "profile.d" / "mamba.xsh";
}
std::pair<std::string, std::string> XonshActivator::update_prompt(const std::string& conda_prompt_modifier)
std::pair<std::string, std::string> XonshActivator::update_prompt(
const std::string& conda_prompt_modifier)
{
return {"", ""};
return { "", "" };
}
std::string XonshActivator::script(const EnvironmentTransform& env_transform)
@ -947,4 +968,4 @@ namespace mamba
return out.str();
}
}
} // namespace mamba

View File

@ -4,6 +4,8 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "channel.hpp"
#include <iostream>
#include <regex>
#include <set>
@ -11,7 +13,6 @@
#include <tuple>
#include <utility>
#include "channel.hpp"
#include "context.hpp"
#include "package_handling.hpp"
#include "url.hpp"
@ -22,50 +23,32 @@ namespace mamba
// Constants used by Channel and ChannelContext
namespace
{
const std::string DEFAULT_CHANNEL_ALIAS = "https://conda.anaconda.org";
const std::map<std::string, std::string> DEFAULT_CUSTOM_CHANNELS = {{"pkgs/pro", "https://repo.anaconda.com"}};
const std::string UNKNOWN_CHANNEL = "<unknown>";
const char DEFAULT_CHANNEL_ALIAS[] = "https://conda.anaconda.org";
const std::map<std::string, std::string> DEFAULT_CUSTOM_CHANNELS
= { { "pkgs/pro", "https://repo.anaconda.com" } };
const char UNKNOWN_CHANNEL[] = "<unknown>";
const std::set<std::string> INVALID_CHANNELS =
{
"<unknown>",
"None:///<unknown>",
"None",
"",
":///<unknown>"
};
const std::set<std::string> INVALID_CHANNELS
= { "<unknown>", "None:///<unknown>", "None", "", ":///<unknown>" };
const std::string LOCAL_CHANNELS_NAME = "local";
const std::string DEFAULT_CHANNELS_NAME = "defaults";
const char LOCAL_CHANNELS_NAME[] = "local";
const char DEFAULT_CHANNELS_NAME[] = "defaults";
const std::vector<std::string> DEFAULT_CHANNELS =
{
const std::vector<std::string> DEFAULT_CHANNELS = {
#ifdef _WIN32
"https://repo.anaconda.com/pkgs/main",
"https://repo.anaconda.com/pkgs/r",
"https://repo.anaconda.com/pkgs/msys2"
#else
"https://repo.anaconda.com/pkgs/main",
"https://repo.anaconda.com/pkgs/r"
"https://repo.anaconda.com/pkgs/main", "https://repo.anaconda.com/pkgs/r"
#endif
};
const std::vector<std::string> KNOWN_PLATFORMS =
{
"noarch",
"linux-32",
"linux-64",
"linux-aarch64",
"linux-armv6l",
"linux-armv7l",
"linux-ppc64",
"linux-ppc64le",
"osx-64",
"win-32",
"win-64",
"zos-z"
};
}
const std::vector<std::string> KNOWN_PLATFORMS
= { "noarch", "linux-32", "linux-64", "linux-aarch64",
"linux-armv6l", "linux-armv7l", "linux-ppc64", "linux-ppc64le",
"osx-64", "win-32", "win-64", "zos-z" };
} // namespace
/**************************
* Channel implementation *
@ -162,9 +145,7 @@ namespace mamba
}
}
std::string Channel::build_url(const std::string& base,
bool with_credential) const
std::string Channel::build_url(const std::string& base, bool with_credential) const
{
if (with_credential && auth() != "")
{
@ -209,13 +190,12 @@ namespace mamba
std::vector<std::string> Channel::urls(const std::vector<std::string>& platforms,
bool with_credential) const
{
if (canonical_name() == UNKNOWN_CHANNEL)
return make_channel(DEFAULT_CHANNELS_NAME).urls(platforms, with_credential);
std::string base = with_credential && token() != ""
? join_url(location(), "t", token(), name())
: join_url(location(), name());
? join_url(location(), "t", token(), name())
: join_url(location(), name());
size_t size = platform() != "" ? (platform() != "noarch" ? 2u : 1u) : platforms.size();
std::vector<std::string> res(size);
@ -229,15 +209,14 @@ namespace mamba
}
else
{
std::transform(platforms.cbegin(), platforms.cend(), res.begin(),
[this, &base, with_credential](const std::string& p)
{
return this->build_url(join_url(base, p), with_credential);
}
);
std::transform(platforms.cbegin(),
platforms.cend(),
res.begin(),
[this, &base, with_credential](const std::string& p) {
return this->build_url(join_url(base, p), with_credential);
});
}
return res;
}
@ -248,11 +227,7 @@ namespace mamba
{
std::string name(channel_name);
std::string location, scheme, auth, token;
split_scheme_auth_token(channel_url,
location,
scheme,
auth,
token);
split_scheme_auth_token(channel_url, location, scheme, auth, token);
if (scheme == "")
{
location = channel_alias.location();
@ -260,7 +235,7 @@ namespace mamba
auth = channel_alias.auth();
token = channel_alias.token();
}
else if(name == "")
else if (name == "")
{
if (channel_alias.location() != "" && starts_with(location, channel_alias.location()))
{
@ -272,7 +247,8 @@ namespace mamba
{
std::string full_url = scheme + "://" + location;
URLHandler parser(full_url);
location = rstrip(URLHandler().set_host(parser.host()).set_port(parser.port()).url(), "/");
location = rstrip(
URLHandler().set_host(parser.host()).set_port(parser.port()).url(), "/");
name = lstrip(parser.path(), "/");
}
}
@ -363,14 +339,17 @@ namespace mamba
const std::string& path)
{
std::string spath = std::string(rstrip(path, "/"));
std::string url = URLHandler().set_scheme(scheme).set_host(host).set_port(port).set_path(spath).url(true);
std::string url
= URLHandler().set_scheme(scheme).set_host(host).set_port(port).set_path(spath).url(
true);
// Case 1: No path given, channel name is ""
if (spath == "")
{
URLHandler handler;
handler.set_host(host).set_port(port);
return channel_configuration(std::string(rstrip(handler.url(), "/")), "", scheme, "", "");
return channel_configuration(
std::string(rstrip(handler.url(), "/")), "", scheme, "", "");
}
// Case 2: migrated_custom_channels not implemented yet
@ -378,11 +357,13 @@ namespace mamba
// Case 4: custom_channels matches
const auto& custom_channels = ChannelContext::instance().get_custom_channels();
for (const auto& ca: custom_channels)
for (const auto& ca : custom_channels)
{
const Channel& channel = ca.second;
std::string test_url = join_url(channel.location(), channel.name());
if (starts_with(url, test_url)) // original code splits with '/' and compares tokens
// original code splits with '/' and compares tokens
if (starts_with(url, test_url))
{
auto subname = std::string(strip(url.replace(0u, test_url.size(), ""), "/"));
return channel_configuration(channel.location(),
@ -405,16 +386,12 @@ namespace mamba
if (host == "")
{
auto sp = rsplit(url, "/", 1);
return channel_configuration(sp[0].size() ? sp[0] : "/",
sp[1],
"file",
"",
"");
return channel_configuration(sp[0].size() ? sp[0] : "/", sp[1], "file", "", "");
}
// Case 7: fallback, channel_location = host:port and channel_name = path,
// bumps the first token of paths starting with /conda for compatibiliy
// with Anaconda Enterprise Repository software
// bumps the first token of paths starting with /conda for
// compatibiliy with Anaconda Enterprise Repository software
spath = lstrip(spath, "/");
std::string bump = "";
if (starts_with(spath, "conda"))
@ -423,11 +400,7 @@ namespace mamba
spath = spath.replace(0, 6, "");
}
std::string location = URLHandler().set_host(host).set_port(port).set_path(bump).url();
return channel_configuration(std::string(strip(location, "/")),
spath,
scheme,
"",
"");
return channel_configuration(std::string(strip(location, "/")), spath, scheme, "", "");
}
Channel Channel::from_url(const std::string& url)
@ -435,10 +408,7 @@ namespace mamba
std::string scheme, host, port, path, auth, token, platform, package_name;
split_conda_url(url, scheme, host, port, path, auth, token, platform, package_name);
auto config = read_channel_configuration(scheme,
host,
port,
path);
auto config = read_channel_configuration(scheme, host, port, path);
return Channel(config.m_scheme.size() ? config.m_scheme : "https",
auth.size() ? auth : config.m_auth,
@ -485,12 +455,8 @@ namespace mamba
else
{
const Channel& alias = ChannelContext::instance().get_channel_alias();
return Channel(alias.scheme(),
alias.auth(),
alias.location(),
alias.token(),
stripped,
platform);
return Channel(
alias.scheme(), alias.auth(), alias.location(), alias.token(), stripped, platform);
}
}
@ -568,12 +534,12 @@ namespace mamba
std::set<std::string> control;
std::vector<std::string> result;
result.reserve(channel_names.size() * platforms.size());
for (const auto& name: channel_names)
for (const auto& name : channel_names)
{
auto multi_iter = ChannelContext::instance().get_custom_multichannels().find(name);
if (multi_iter != ChannelContext::instance().get_custom_multichannels().end())
{
for (const auto& n: multi_iter->second)
for (const auto& n : multi_iter->second)
{
append_channel_urls(n, platforms, with_credential, result, control);
}
@ -593,8 +559,8 @@ namespace mamba
{
// TODO that doesn't seem very logical
std::vector<std::string> platforms = platform.size()
? std::vector<std::string>({ platform, "noarch" })
: Context::instance().platforms();
? std::vector<std::string>({ platform, "noarch" })
: Context::instance().platforms();
if (append_context_channels || use_local)
{
@ -624,21 +590,20 @@ namespace mamba
if (whitelist.size())
{
std::vector<std::string> accepted_urls(whitelist.size());
std::transform(whitelist.begin(), whitelist.end(), accepted_urls.begin(),
[](const std::string& url) { return make_channel(url).base_url(); });
std::for_each(urls.begin(), urls.end(), [&accepted_urls](const std::string& s)
std::transform(whitelist.begin(),
whitelist.end(),
accepted_urls.begin(),
[](const std::string& url) { return make_channel(url).base_url(); });
std::for_each(urls.begin(), urls.end(), [&accepted_urls](const std::string& s) {
auto it = std::find(
accepted_urls.begin(), accepted_urls.end(), make_channel(s).base_url());
if (it == accepted_urls.end())
{
auto it = std::find(accepted_urls.begin(),
accepted_urls.end(),
make_channel(s).base_url());
if (it == accepted_urls.end())
{
std::ostringstream str;
str << "Channel " << s << " not allowed";
throw std::runtime_error(str.str().c_str());
}
std::ostringstream str;
str << "Channel " << s << " not allowed";
throw std::runtime_error(str.str().c_str());
}
);
});
}
}
@ -684,11 +649,7 @@ namespace mamba
Channel ChannelContext::build_channel_alias()
{
std::string location, scheme, auth, token;
split_scheme_auth_token(DEFAULT_CHANNEL_ALIAS,
location,
scheme,
auth,
token);
split_scheme_auth_token(DEFAULT_CHANNEL_ALIAS, location, scheme, auth, token);
return Channel(scheme, auth, location, token);
}
@ -701,9 +662,10 @@ namespace mamba
// Default channels
std::vector<std::string> default_names(DEFAULT_CHANNELS.size());
auto name_iter = default_names.begin();
for(auto& url: DEFAULT_CHANNELS)
for (auto& url : DEFAULT_CHANNELS)
{
auto channel = Channel::make_simple_channel(m_channel_alias, url, "", DEFAULT_CHANNELS_NAME);
auto channel
= Channel::make_simple_channel(m_channel_alias, url, "", DEFAULT_CHANNELS_NAME);
std::string name = channel.name();
auto res = m_custom_channels.emplace(std::move(name), std::move(channel));
*name_iter++ = res.first->first;
@ -711,21 +673,20 @@ namespace mamba
m_custom_multichannels.emplace(DEFAULT_CHANNELS_NAME, std::move(default_names));
// Local channels
std::vector<std::string> local_channels =
{
Context::instance().target_prefix.string() + "/conda-bld",
Context::instance().root_prefix.string() + "/conda-bld",
"~/conda-bld"
};
std::vector<std::string> local_channels
= { Context::instance().target_prefix.string() + "/conda-bld",
Context::instance().root_prefix.string() + "/conda-bld",
"~/conda-bld" };
std::vector<std::string> local_names;
local_names.reserve(local_channels.size());
for(const auto& p: local_channels)
for (const auto& p : local_channels)
{
if (fs::is_directory(p))
{
std::string url = path_to_url(p);
auto channel = Channel::make_simple_channel(m_channel_alias, url, "", LOCAL_CHANNELS_NAME);
auto channel
= Channel::make_simple_channel(m_channel_alias, url, "", LOCAL_CHANNELS_NAME);
std::string name = channel.name();
auto res = m_custom_channels.emplace(std::move(name), std::move(channel));
local_names.push_back(res.first->first);
@ -738,9 +699,10 @@ namespace mamba
*******************/
// Default local channel
for(auto& ch: DEFAULT_CUSTOM_CHANNELS)
for (auto& ch : DEFAULT_CUSTOM_CHANNELS)
{
m_custom_channels.emplace(ch.first, Channel::make_simple_channel(m_channel_alias, ch.second, ch.first));
m_custom_channels.emplace(
ch.first, Channel::make_simple_channel(m_channel_alias, ch.second, ch.first));
}
}
}
} // namespace mamba

View File

@ -4,13 +4,14 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "context.hpp"
#include <csignal>
#include "output.hpp"
#include "util.hpp"
#include "context.hpp"
#include "thirdparty/termcolor.hpp"
#include "thread_utils.hpp"
#include "util.hpp"
namespace mamba
{
@ -18,45 +19,45 @@ namespace mamba
{
// armv6l and armv7l
#if defined(__arm__) || defined(__thumb__)
#ifdef ___ARM_ARCH_6__
const std::string MAMBA_PLATFORM = "armv6l";
#elif __ARM_ARCH_7__
const std::string MAMBA_PLATFORM = "armv7l";
#else
#error "Unknown platform"
#endif
#elif _M_ARM==6
const std::string MAMBA_PLATFORM = "armv6l";
#elif _M_ARM==7
const std::string MAMBA_PLATFORM = "armv7l";
#ifdef ___ARM_ARCH_6__
static const char MAMBA_PLATFORM[] = "armv6l";
#elif __ARM_ARCH_7__
static const char MAMBA_PLATFORM[] = "armv7l";
#else
#error "Unknown platform"
#endif
#elif _M_ARM == 6
static const char MAMBA_PLATFORM[] = "armv6l";
#elif _M_ARM == 7
static const char MAMBA_PLATFORM[] = "armv7l";
// aarch64
#elif defined(__aarch64__)
const std::string MAMBA_PLATFORM = "aarch64";
static const char MAMBA_PLATFORM[] = "aarch64";
#elif defined(__ppc64__) || defined(__powerpc64__)
#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
const std::string MAMBA_PLATFORM = "ppc64";
#else
const std::string MAMBA_PLATFORM = "ppc64le";
#endif
#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
static const char MAMBA_PLATFORM[] = "ppc64";
#else
static const char MAMBA_PLATFORM[] = "ppc64le";
#endif
// Linux
#elif defined(__linux__)
#if __x86_64__
const std::string MAMBA_PLATFORM = "linux-64";
#else
const std::string MAMBA_PLATFORM = "linux-32";
#endif
#if __x86_64__
static const char MAMBA_PLATFORM[] = "linux-64";
#else
static const char MAMBA_PLATFORM[] = "linux-32";
#endif
// OSX
#elif defined(__APPLE__) || defined(__MACH__)
const std::string MAMBA_PLATFORM = "osx-64";
static const char MAMBA_PLATFORM[] = "osx-64";
// Windows
#elif defined(_WIN64)
const std::string MAMBA_PLATFORM = "win-64";
#elif defined (_WIN32)
const std::string MAMBA_PLATFORM = "win-32";
static const char MAMBA_PLATFORM[] = "win-64";
#elif defined(_WIN32)
static const char MAMBA_PLATFORM[] = "win-32";
#else
#error "Unknown platform"
#error "Unknown platform"
#endif
}
} // namespace
Context::Context()
{
set_verbosity(0);
@ -144,4 +145,4 @@ namespace mamba
throw std::runtime_error("Environment name not found " + name);
}
}
} // namespace mamba

View File

@ -4,13 +4,14 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "fetch.hpp"
#include <string_view>
#include <thread>
#include "context.hpp"
#include "fetch.hpp"
#include "util.hpp"
#include "thread_utils.hpp"
#include "util.hpp"
namespace mamba
{
@ -18,7 +19,9 @@ namespace mamba
* DownloadTarget implementation *
*********************************/
DownloadTarget::DownloadTarget(const std::string& name, const std::string& url, const std::string& filename)
DownloadTarget::DownloadTarget(const std::string& name,
const std::string& url,
const std::string& filename)
: m_name(name)
, m_filename(filename)
, m_url(url)
@ -43,7 +46,8 @@ namespace mamba
m_headers = nullptr;
if (ends_with(url, ".json"))
{
curl_easy_setopt(m_handle, CURLOPT_ACCEPT_ENCODING, "gzip, deflate, compress, identity");
curl_easy_setopt(
m_handle, CURLOPT_ACCEPT_ENCODING, "gzip, deflate, compress, identity");
m_headers = curl_slist_append(m_headers, "Content-Type: application/json");
}
curl_easy_setopt(m_handle, CURLOPT_HTTPHEADER, m_headers);
@ -51,11 +55,12 @@ namespace mamba
curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, 1L);
// DO NOT SET TIMEOUT as it will also take into account multi-start time and it's just wrong
// curl_easy_setopt(m_handle, CURLOPT_TIMEOUT, Context::instance().read_timeout_secs);
// DO NOT SET TIMEOUT as it will also take into account multi-start time and
// it's just wrong curl_easy_setopt(m_handle, CURLOPT_TIMEOUT,
// Context::instance().read_timeout_secs);
// TODO while libcurl in conda now _has_ http2 support we need to fix mamba to work properly with it
// this includes:
// TODO while libcurl in conda now _has_ http2 support we need to fix mamba to
// work properly with it this includes:
// - setting the cache stuff correctly
// - fixing how the progress bar works
curl_easy_setopt(m_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
@ -64,7 +69,8 @@ namespace mamba
curl_easy_setopt(m_handle, CURLOPT_LOW_SPEED_TIME, 60L);
curl_easy_setopt(m_handle, CURLOPT_LOW_SPEED_LIMIT, 30L);
curl_easy_setopt(m_handle, CURLOPT_CONNECTTIMEOUT, Context::instance().connect_timeout_secs);
curl_easy_setopt(
m_handle, CURLOPT_CONNECTTIMEOUT, Context::instance().connect_timeout_secs);
std::string& ssl_verify = Context::instance().ssl_verify;
@ -96,9 +102,8 @@ namespace mamba
bool DownloadTarget::can_retry()
{
return m_retries < size_t(Context::instance().max_retries) &&
http_status >= 500 &&
!starts_with(m_url, "file://");
return m_retries < size_t(Context::instance().max_retries) && http_status >= 500
&& !starts_with(m_url, "file://");
}
CURL* DownloadTarget::retry()
@ -115,7 +120,8 @@ namespace mamba
init_curl_target(m_url);
if (m_has_progress_bar)
{
curl_easy_setopt(m_handle, CURLOPT_XFERINFOFUNCTION, &DownloadTarget::progress_callback);
curl_easy_setopt(
m_handle, CURLOPT_XFERINFOFUNCTION, &DownloadTarget::progress_callback);
curl_easy_setopt(m_handle, CURLOPT_XFERINFODATA, this);
}
m_retry_wait_seconds = m_retry_wait_seconds * Context::instance().retry_backoff;
@ -135,16 +141,16 @@ namespace mamba
curl_slist_free_all(m_headers);
}
size_t DownloadTarget::write_callback(char *ptr, size_t size, size_t nmemb, void *self)
size_t DownloadTarget::write_callback(char* ptr, size_t size, size_t nmemb, void* self)
{
auto* s = (DownloadTarget*)self;
auto* s = reinterpret_cast<DownloadTarget*>(self);
s->m_file.write(ptr, size * nmemb);
return size * nmemb;
}
size_t DownloadTarget::header_callback(char *buffer, size_t size, size_t nitems, void *self)
size_t DownloadTarget::header_callback(char* buffer, size_t size, size_t nitems, void* self)
{
auto* s = (DownloadTarget*)self;
auto* s = reinterpret_cast<DownloadTarget*>(self);
std::string_view header(buffer, size * nitems);
auto colon_idx = header.find(':');
@ -177,7 +183,8 @@ namespace mamba
return nitems * size;
}
int DownloadTarget::progress_callback(void*, curl_off_t total_to_download, curl_off_t now_downloaded, curl_off_t, curl_off_t)
int DownloadTarget::progress_callback(
void*, curl_off_t total_to_download, curl_off_t now_downloaded, curl_off_t, curl_off_t)
{
if (Context::instance().quiet || Context::instance().json)
{
@ -199,7 +206,8 @@ namespace mamba
if ((total_to_download != 0 || m_expected_size != 0) && now_downloaded != 0)
{
double perc = double(now_downloaded) / double(total_to_download);
double perc
= static_cast<double>(now_downloaded) / static_cast<double>(total_to_download);
std::stringstream postfix;
postfix << std::setw(6);
to_human_readable_filesize(postfix, now_downloaded);
@ -234,11 +242,13 @@ namespace mamba
if (mod_etag.find("_etag") != mod_etag.end())
{
m_headers = curl_slist_append(m_headers, to_header("If-None-Match", mod_etag["_etag"]).c_str());
m_headers = curl_slist_append(m_headers,
to_header("If-None-Match", mod_etag["_etag"]).c_str());
}
if (mod_etag.find("_mod") != mod_etag.end())
{
m_headers = curl_slist_append(m_headers, to_header("If-Modified-Since", mod_etag["_mod"]).c_str());
m_headers = curl_slist_append(m_headers,
to_header("If-Modified-Since", mod_etag["_mod"]).c_str());
}
}
@ -289,11 +299,12 @@ namespace mamba
curl_easy_getinfo(m_handle, CURLINFO_EFFECTIVE_URL, &effective_url);
std::stringstream err;
err << "Download error (" << result << ") " <<
curl_easy_strerror(result) << " [" << effective_url << "]";
err << "Download error (" << result << ") " << curl_easy_strerror(result) << " ["
<< effective_url << "]";
LOG_WARNING << err.str();
m_next_retry = std::chrono::steady_clock::now() + std::chrono::seconds(m_retry_wait_seconds);
m_next_retry
= std::chrono::steady_clock::now() + std::chrono::seconds(m_retry_wait_seconds);
m_progress_bar.set_progress(0);
m_progress_bar.set_postfix(curl_easy_strerror(result));
if (m_ignore_failure == false && can_retry() == false)
@ -317,12 +328,14 @@ namespace mamba
curl_easy_getinfo(m_handle, CURLINFO_EFFECTIVE_URL, &effective_url);
curl_easy_getinfo(m_handle, CURLINFO_SIZE_DOWNLOAD_T, &downloaded_size);
LOG_INFO << "Transfer finalized, status: " << http_status << " [" << effective_url << "] " << downloaded_size << " bytes";
LOG_INFO << "Transfer finalized, status: " << http_status << " [" << effective_url << "] "
<< downloaded_size << " bytes";
if (http_status >= 500 && can_retry())
{
// this request didn't work!
m_next_retry = std::chrono::steady_clock::now() + std::chrono::seconds(m_retry_wait_seconds);
m_next_retry
= std::chrono::steady_clock::now() + std::chrono::seconds(m_retry_wait_seconds);
std::stringstream msg;
msg << "Failed (" << http_status << "), retry in " << m_retry_wait_seconds << "s";
m_progress_bar.set_progress(0);
@ -354,8 +367,8 @@ namespace mamba
MultiDownloadTarget::MultiDownloadTarget()
{
m_handle = curl_multi_init();
curl_multi_setopt(m_handle, CURLMOPT_MAX_TOTAL_CONNECTIONS,
Context::instance().max_parallel_downloads);
curl_multi_setopt(
m_handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, Context::instance().max_parallel_downloads);
}
MultiDownloadTarget::~MultiDownloadTarget()
@ -365,7 +378,8 @@ namespace mamba
void MultiDownloadTarget::add(DownloadTarget* target)
{
if (!target) return;
if (!target)
return;
CURLMcode code = curl_multi_add_handle(m_handle, target->handle());
if (code != CURLM_CALL_MULTI_PERFORM)
{
@ -380,7 +394,7 @@ namespace mamba
bool MultiDownloadTarget::check_msgs(bool failfast)
{
int msgs_in_queue;
CURLMsg *msg;
CURLMsg* msg;
while ((msg = curl_multi_info_read(m_handle, &msgs_in_queue)))
{
@ -449,7 +463,7 @@ namespace mamba
{
CURLMcode code = curl_multi_perform(m_handle, &still_running);
if(code != CURLM_OK)
if (code != CURLM_OK)
{
throw std::runtime_error(curl_multi_strerror(code));
}
@ -474,17 +488,17 @@ namespace mamba
}
}
long curl_timeout = -1;
long curl_timeout = -1; // NOLINT(runtime/int)
code = curl_multi_timeout(m_handle, &curl_timeout);
if (code != CURLM_OK)
{
throw std::runtime_error(curl_multi_strerror(code));
}
if (curl_timeout == 0) // No wait
if (curl_timeout == 0) // No wait
continue;
if (curl_timeout < 0 || curl_timeout > max_wait_msecs) // Wait no more than 1s
if (curl_timeout < 0 || curl_timeout > max_wait_msecs) // Wait no more than 1s
curl_timeout = max_wait_msecs;
int numfds;
@ -494,10 +508,10 @@ namespace mamba
throw std::runtime_error(curl_multi_strerror(code));
}
if(!numfds)
if (!numfds)
{
repeats++; // count number of repeated zero numfds
if(repeats > 1)
repeats++; // count number of repeated zero numfds
if (repeats > 1)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
@ -506,8 +520,7 @@ namespace mamba
{
repeats = 0;
}
}
while ((still_running || !m_retry_targets.empty()) && !is_sig_interrupted());
} while ((still_running || !m_retry_targets.empty()) && !is_sig_interrupted());
if (is_sig_interrupted())
{
@ -517,4 +530,4 @@ namespace mamba
}
return true;
}
}
} // namespace mamba

View File

@ -4,17 +4,17 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "history.hpp"
#include <fstream>
#include "history.hpp"
#include "fsutil.hpp"
namespace mamba
{
History::History(const std::string& prefix)
: m_prefix(prefix),
m_history_file_path(fs::path(m_prefix) / "conda-meta" / "history")
: m_prefix(prefix)
, m_history_file_path(fs::path(m_prefix) / "conda-meta" / "history")
{
}
@ -35,7 +35,8 @@ namespace mamba
while (getline(in_file, line))
{
// line.strip()
if (line.size() == 0) continue;
if (line.size() == 0)
continue;
std::smatch base_match;
if (std::regex_match(line, base_match, head_re))
{
@ -67,7 +68,6 @@ namespace mamba
{
req.cmd = rmatch[1].str();
}
else if (std::regex_match(line, rmatch, conda_v_pat))
{
req.conda_version = rmatch[1].str();
@ -234,8 +234,10 @@ namespace mamba
out << "+" << link_dist << std::endl;
}
auto specs_output = [](const std::string& action, const std::vector<std::string>& specs) -> std::string {
if (specs.empty()) return "";
auto specs_output = [](const std::string& action,
const std::vector<std::string>& specs) -> std::string {
if (specs.empty())
return "";
std::stringstream spec_ss;
spec_ss << "# " << action << " specs: [";
for (auto spec : specs)
@ -253,4 +255,4 @@ namespace mamba
out << specs_output("neutered", entry.neutered);
}
}
}
} // namespace mamba

View File

@ -4,22 +4,24 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <regex>
#include "link.hpp"
#include "output.hpp"
#include "validate.hpp"
#include "environment.hpp"
#include "util.hpp"
#include "match_spec.hpp"
#include "transaction_context.hpp"
#include <regex>
#include <string>
#include <tuple>
#include <vector>
#include "environment.hpp"
#include "match_spec.hpp"
#include "output.hpp"
#include "thirdparty/subprocess.hpp"
#include "transaction_context.hpp"
#include "util.hpp"
#include "validate.hpp"
namespace mamba
{
void python_entry_point_template(std::ostream& out,
const python_entry_point_parsed& p)
void python_entry_point_template(std::ostream& out, const python_entry_point_parsed& p)
{
auto import_name = split(p.func, ".")[0];
out << "# -*- coding: utf-8 -*-\n";
@ -29,11 +31,13 @@ namespace mamba
out << "from " << p.module << " import " << import_name << "\n\n";
out << "if __name__ == '__main__':\n";
out << " sys.argv[0] = re.sub(r'(-script\\.pyw?|\\.exe)?$', '', sys.argv[0])\n";
out << " sys.argv[0] = re.sub(r'(-script\\.pyw?|\\.exe)?$', '', "
"sys.argv[0])\n";
out << " sys.exit(" << p.func << "())\n";
}
void application_entry_point_template(std::ostream& out, const std::string_view& source_full_path)
void application_entry_point_template(std::ostream& out,
const std::string_view& source_full_path)
{
out << "# -*- coding: utf-8 -*-\n";
out << "if __name__ == '__main__':\n";
@ -64,7 +68,8 @@ namespace mamba
auto py_file_stem = py_path.stem();
std::string py_ver_nodot = py_ver;
replace_all(py_ver_nodot, ".", "");
return directory / fs::path("__pycache__") / concat(py_file_stem.c_str(), ".cpython-", py_ver_nodot, ".pyc");
return directory / fs::path("__pycache__")
/ concat(py_file_stem.c_str(), ".cpython-", py_ver_nodot, ".pyc");
}
}
@ -92,12 +97,16 @@ namespace mamba
auto path_begin = shebang.find_first_not_of(WHITESPACES);
auto path_end = shebang.substr(path_begin).find_first_not_of(WHITESPACES);
fs::path shebang_path = shebang.substr(path_begin, path_end);
return concat("#!/usr/bin/env ", std::string(shebang_path.filename()), " ", shebang.substr(path_end));
return concat("#!/usr/bin/env ",
std::string(shebang_path.filename()),
" ",
shebang.substr(path_end));
}
}
// for noarch python packages that have entry points
auto LinkPackage::create_python_entry_point(const fs::path& path, const python_entry_point_parsed& entry_point)
auto LinkPackage::create_python_entry_point(const fs::path& path,
const python_entry_point_parsed& entry_point)
{
fs::path target = m_context->target_prefix / path;
if (fs::exists(target))
@ -105,15 +114,15 @@ namespace mamba
throw std::runtime_error("clobber warning");
}
#ifdef _WIN32
// We add -script.py to WIN32, and link the conda.exe launcher which will automatically find
// the correct script to launch
#ifdef _WIN32
// We add -script.py to WIN32, and link the conda.exe launcher which will
// automatically find the correct script to launch
std::string win_script = path;
win_script += "-script.py";
std::ofstream out_file(m_context->target_prefix / win_script);
#else
#else
std::ofstream out_file(target);
#endif
#endif
fs::path python_path;
if (m_context->has_python)
@ -137,11 +146,13 @@ namespace mamba
python_entry_point_template(out_file, entry_point);
out_file.close();
#ifdef _WIN32
#ifdef _WIN32
fs::path conda_exe = Context::instance().conda_prefix / "Scripts" / "conda.exe";
if (!fs::exists(conda_exe))
{
throw std::runtime_error("Cannot link noarch package entrypoint conda.exe because conda.exe is not installed.");
throw std::runtime_error(
"Cannot link noarch package entrypoint conda.exe because conda.exe is "
"not installed.");
}
fs::path script_exe = path;
script_exe.replace_extension("exe");
@ -154,14 +165,14 @@ namespace mamba
LOG_INFO << "Linking exe " << conda_exe << " --> " << script_exe;
fs::create_hard_link(conda_exe, m_context->target_prefix / script_exe);
make_executable(m_context->target_prefix / script_exe);
return std::array<std::string, 2>{win_script, script_exe};
#else
return std::array<std::string, 2>{ win_script, script_exe };
#else
if (!python_path.empty())
{
make_executable(target);
}
return path;
#endif
#endif
}
std::string ensure_pad(const std::string& str, char pad = '_')
@ -189,16 +200,18 @@ namespace mamba
std::string win_path_double_escape(const std::string& path)
{
#ifdef _WIN32
#ifdef _WIN32
std::string path_copy = path;
replace_all(path_copy, "\\", "\\\\");
return path_copy;
#else
#else
return path;
#endif
#endif
}
void create_application_entry_point(const fs::path& source_full_path, const fs::path& target_full_path, const fs::path& python_full_path)
void create_application_entry_point(const fs::path& source_full_path,
const fs::path& target_full_path,
const fs::path& python_full_path)
{
// source_full_path: where the entry point file points to
// target_full_path: the location of the new entry point file being created
@ -220,10 +233,11 @@ namespace mamba
make_executable(target_full_path);
}
// def create_application_entry_point(source_full_path, target_full_path, python_full_path):
// def create_application_entry_point(source_full_path, target_full_path,
// python_full_path):
// # source_full_path: where the entry point file points to
// # target_full_path: the location of the new entry point file being created
// if lexists(target_full_path):
// # target_full_path: the location of the new entry point file being
// created if lexists(target_full_path):
// maybe_raise(BasicClobberError(
// source_path=None,
// target_path=target_full_path,
@ -277,7 +291,8 @@ namespace mamba
}
if (!fs::is_regular_file(cmd_exe))
{
LOG_WARNING << "cmd.exe could not be found. Looked in SystemRoot and windir env vars.";
LOG_WARNING << "cmd.exe could not be found. Looked in SystemRoot and "
"windir env vars.";
}
else
{
@ -288,15 +303,15 @@ namespace mamba
}
std::unique_ptr<TemporaryFile> wrap_call(const fs::path& root_prefix,
const fs::path& prefix,
bool dev_mode,
bool debug_wrapper_scripts,
const std::vector<std::string>& arguments)
const fs::path& prefix,
bool dev_mode,
bool debug_wrapper_scripts,
const std::vector<std::string>& arguments)
{
// todo add abspath here
fs::path tmp_prefix = prefix / ".tmp";
#ifdef _WIN32
#ifdef _WIN32
ensure_comspec_set();
std::string comspec = env::get("COMSPEC");
std::string conda_bat;
@ -322,12 +337,15 @@ namespace mamba
std::ofstream out(tf->path());
std::string silencer;
if (!debug_wrapper_scripts) silencer = "@";
if (!debug_wrapper_scripts)
silencer = "@";
out << silencer << "ECHO OFF\n";
out << silencer << "SET PYTHONIOENCODING=utf-8\n";
out << silencer << "SET PYTHONUTF8=1\n";
out << silencer << "FOR /F \"tokens=2 delims=:.\" %%A in (\'chcp\') do for %%B in (%%A) do set \"_CONDA_OLD_CHCP=%%B\"\n";
out << silencer
<< "FOR /F \"tokens=2 delims=:.\" %%A in (\'chcp\') do for %%B in (%%A) "
"do set \"_CONDA_OLD_CHCP=%%B\"\n";
out << silencer << "chcp 65001 > NUL\n";
if (dev_mode)
@ -338,7 +356,9 @@ namespace mamba
// 'python -m conda'
// *with* PYTHONPATH set.
out << silencer << "SET PYTHONPATH=" << CONDA_PACKAGE_ROOT << "\n";
out << silencer << "SET CONDA_EXE=" << "python.exe" << "\n"; // TODO this should be `sys.executable`
out << silencer << "SET CONDA_EXE="
<< "python.exe"
<< "\n"; // TODO this should be `sys.executable`
out << silencer << "SET _CE_M=-m\n";
out << silencer << "SET _CE_CONDA=conda\n";
}
@ -357,11 +377,11 @@ namespace mamba
out << "SET 1>&2\n";
}
#else
#else
// During tests, we sometimes like to have a temp env with e.g. an old python in it
// and have it run tests against the very latest development sources. For that to
// work we need extra smarts here, we want it to be instead:
// During tests, we sometimes like to have a temp env with e.g. an old python
// in it and have it run tests against the very latest development sources.
// For that to work we need extra smarts here, we want it to be instead:
std::string shebang;
std::string dev_arg;
if (dev_mode)
@ -409,9 +429,8 @@ namespace mamba
<< ">&2 env\n";
}
out << "\n"
<< join(" ", arguments);
#endif
out << "\n" << join(" ", arguments);
#endif
out.close();
@ -419,27 +438,32 @@ namespace mamba
}
/*
call the post-link or pre-unlink script and return true / false on success / failure
call the post-link or pre-unlink script and return true / false on success /
failure
*/
bool run_script(const fs::path& prefix, const PackageInfo& pkg_info,
bool run_script(const fs::path& prefix,
const PackageInfo& pkg_info,
const std::string& action = "post-link",
const std::string& env_prefix = "",
bool activate = false)
{
#ifdef _WIN32
auto path = prefix / get_bin_directory_short_path() / concat(".", pkg_info.name, "-", action, ".bat");
#else
auto path = prefix / get_bin_directory_short_path() / concat(".", pkg_info.name, "-", action, ".sh");
#endif
#ifdef _WIN32
auto path = prefix / get_bin_directory_short_path()
/ concat(".", pkg_info.name, "-", action, ".bat");
#else
auto path = prefix / get_bin_directory_short_path()
/ concat(".", pkg_info.name, "-", action, ".sh");
#endif
if (!fs::exists(path))
{
LOG_INFO << action << " script for " << pkg_info.name << " does not exist (" << path << ")";
LOG_INFO << action << " script for " << pkg_info.name << " does not exist (" << path
<< ")";
return true;
}
// TODO impl.
std::map<std::string, std::string> envmap; // = env::copy();
std::map<std::string, std::string> envmap; // = env::copy();
if (action == "pre-link")
{
@ -450,27 +474,31 @@ namespace mamba
std::vector<std::string> command_args;
std::unique_ptr<TemporaryFile> script_file;
#ifdef _WIN32
#ifdef _WIN32
ensure_comspec_set();
std::string comspec = env::get("COMSPEC");
if (comspec.size() == 0)
{
LOG_ERROR << "Failed to run " << action << " for " << pkg_info.name << " due to COMSPEC not set in env vars.";
LOG_ERROR << "Failed to run " << action << " for " << pkg_info.name
<< " due to COMSPEC not set in env vars.";
return false;
}
if (activate)
{
script_file = wrap_call(Context::instance().root_prefix, prefix,
Context::instance().dev, false, {"@CALL", path});
script_file = wrap_call(Context::instance().root_prefix,
prefix,
Context::instance().dev,
false,
{ "@CALL", path });
command_args = {comspec, "/d", "/c", script_file->path()};
command_args = { comspec, "/d", "/c", script_file->path() };
}
else
{
command_args = {comspec, "/d", "/c", path};
command_args = { comspec, "/d", "/c", path };
}
#else
#else
// shell_path = 'sh' if 'bsd' in sys.platform else 'bash'
fs::path shell_path = env::which("bash");
if (shell_path.empty())
@ -481,13 +509,11 @@ namespace mamba
if (activate)
{
// std::string caller
script_file = wrap_call(
Context::instance().root_prefix,
prefix,
Context::instance().dev,
false,
{".", path}
);
script_file = wrap_call(Context::instance().root_prefix,
prefix,
Context::instance().dev,
false,
{ ".", path });
command_args.push_back(shell_path);
command_args.push_back(script_file->path());
}
@ -497,7 +523,7 @@ namespace mamba
command_args.push_back("-x");
command_args.push_back(path);
}
#endif
#endif
envmap["ROOT_PREFIX"] = Context::instance().root_prefix;
envmap["PREFIX"] = env_prefix.size() ? env_prefix : std::string(prefix);
@ -509,10 +535,12 @@ namespace mamba
std::string cargs = join(" ", command_args);
envmap["PATH"] = concat(path.parent_path().c_str(), env::pathsep(), PATH);
LOG_DEBUG << "For " << pkg_info.name << " at " << envmap["PREFIX"] << ", executing script: $ " << cargs;
LOG_DEBUG << "For " << pkg_info.name << " at " << envmap["PREFIX"]
<< ", executing script: $ " << cargs;
LOG_WARNING << "Calling " << cargs;
int response = subprocess::call(cargs, subprocess::environment{envmap}, subprocess::cwd{path.parent_path()});
int response = subprocess::call(
cargs, subprocess::environment{ envmap }, subprocess::cwd{ path.parent_path() });
auto msg = get_prefix_messages(envmap["PREFIX"]);
if (Context::instance().json)
{
@ -536,7 +564,9 @@ namespace mamba
return true;
}
UnlinkPackage::UnlinkPackage(const PackageInfo& pkg_info, const fs::path& cache_path, TransactionContext* context)
UnlinkPackage::UnlinkPackage(const PackageInfo& pkg_info,
const fs::path& cache_path,
TransactionContext* context)
: m_pkg_info(pkg_info)
, m_cache_path(cache_path)
, m_specifier(m_pkg_info.str())
@ -588,7 +618,9 @@ namespace mamba
return lp.execute();
}
LinkPackage::LinkPackage(const PackageInfo& pkg_info, const fs::path& cache_path, TransactionContext* context)
LinkPackage::LinkPackage(const PackageInfo& pkg_info,
const fs::path& cache_path,
TransactionContext* context)
: m_pkg_info(pkg_info)
, m_cache_path(cache_path)
, m_source(cache_path / m_pkg_info.str())
@ -596,7 +628,8 @@ namespace mamba
{
}
std::tuple<std::string, std::string> LinkPackage::link_path(const PathData& path_data, bool noarch_python)
std::tuple<std::string, std::string> LinkPackage::link_path(const PathData& path_data,
bool noarch_python)
{
std::string subtarget = path_data.path;
LOG_INFO << "linking path " << subtarget;
@ -650,10 +683,11 @@ namespace mamba
std::string padding(path_data.prefix_placeholder.size() - new_prefix.size(), '\0');
auto binary_replace = [&](std::size_t pos, std::size_t end, const std::string& suffix) {
std::string replacement = concat(new_prefix, suffix, padding);
buffer.replace(pos, end - pos, replacement);
};
auto binary_replace
= [&](std::size_t pos, std::size_t end, const std::string& suffix) {
std::string replacement = concat(new_prefix, suffix, padding);
buffer.replace(pos, end - pos, replacement);
};
std::size_t pos = buffer.find(path_data.prefix_placeholder);
while (pos != std::string::npos)
@ -672,7 +706,9 @@ namespace mamba
}
}
auto open_mode = (path_data.file_mode == FileMode::BINARY) ? std::ios::out | std::ios::binary : std::ios::out;
auto open_mode = (path_data.file_mode == FileMode::BINARY)
? std::ios::out | std::ios::binary
: std::ios::out;
std::ofstream fo(dst, open_mode);
fo << buffer;
fo.close();
@ -694,7 +730,8 @@ namespace mamba
}
else
{
throw std::runtime_error(std::string("Path type not implemented: ") + std::to_string((int)path_data.path_type));
throw std::runtime_error(std::string("Path type not implemented: ")
+ std::to_string(static_cast<int>(path_data.path_type)));
}
// TODO we could also use the SHA256 sum of the paths json
return std::make_tuple(validate::sha256sum(dst), rel_dst);
@ -719,21 +756,26 @@ namespace mamba
}
all_py_files_f.close();
// TODO use the real python file here?!
std::vector<std::string> command = {
m_context->target_prefix / m_context->python_path,
"-Wi", "-m", "compileall", "-q", "-l", "-i",
all_py_files.path()
};
std::vector<std::string> command = { m_context->target_prefix / m_context->python_path,
"-Wi",
"-m",
"compileall",
"-q",
"-l",
"-i",
all_py_files.path() };
auto py_ver_split = split(m_context->python_version, ".");
if (std::stoi(std::string(py_ver_split[0])) >= 3 && std::stoi(std::string(py_ver_split[1])) > 5)
if (std::stoi(std::string(py_ver_split[0])) >= 3
&& std::stoi(std::string(py_ver_split[1])) > 5)
{
// activate parallel pyc compilation
command.push_back("-j0");
}
auto out = subprocess::check_output(command, subprocess::cwd{std::string(m_context->target_prefix)});
auto out = subprocess::check_output(
command, subprocess::cwd{ std::string(m_context->target_prefix) });
return pyc_files;
}
@ -790,13 +832,12 @@ namespace mamba
paths_json["paths_version"] = 1;
for (auto& path : paths_data)
{
auto [sha256_in_prefix, final_path] = link_path(path, noarch_type == NoarchType::PYTHON);
auto [sha256_in_prefix, final_path]
= link_path(path, noarch_type == NoarchType::PYTHON);
files_record.push_back(final_path);
nlohmann::json json_record = {
{"_path", final_path},
{"sha256_in_prefix", sha256_in_prefix}
};
nlohmann::json json_record
= { { "_path", final_path }, { "sha256_in_prefix", sha256_in_prefix } };
if (!path.sha256.empty())
{
@ -829,9 +870,9 @@ namespace mamba
paths_json["paths"].push_back(json_record);
}
std::string f_name = index_json["name"].get<std::string>() + "-" +
index_json["version"].get<std::string>() + "-" +
index_json["build"].get<std::string>();
std::string f_name = index_json["name"].get<std::string>() + "-"
+ index_json["version"].get<std::string>() + "-"
+ index_json["build"].get<std::string>();
out_json = index_json;
out_json["paths_data"] = paths_json;
@ -841,10 +882,7 @@ namespace mamba
out_json["extracted_package_dir"] = m_source;
// TODO find out what `1` means
out_json["link"] = {
{"source", std::string(m_source)},
{"type", 1}
};
out_json["link"] = { { "source", std::string(m_source) }, { "type", 1 } };
if (noarch_type == NoarchType::PYTHON)
{
@ -862,7 +900,8 @@ namespace mamba
{
if (std::regex_match(sub_path_json.path, py_file_re))
{
for_compilation.push_back(get_python_noarch_target_path(sub_path_json.path, m_context->site_packages_path));
for_compilation.push_back(get_python_noarch_target_path(
sub_path_json.path, m_context->site_packages_path));
}
}
@ -871,46 +910,36 @@ namespace mamba
for (const fs::path& pyc_path : pyc_files)
{
out_json["paths_data"]["paths"].push_back(
{
{"_path", std::string(pyc_path)},
{"path_type", "pyc_file"}
});
{ { "_path", std::string(pyc_path) }, { "path_type", "pyc_file" } });
out_json["files"].push_back(pyc_path);
}
if (link_json.find("noarch") != link_json.end() &&
link_json["noarch"].find("entry_points") != link_json["noarch"].end())
if (link_json.find("noarch") != link_json.end()
&& link_json["noarch"].find("entry_points") != link_json["noarch"].end())
{
for (auto& ep : link_json["noarch"]["entry_points"])
{
// install entry points
auto entry_point_parsed = parse_entry_point(ep.get<std::string>());
auto entry_point_path = get_bin_directory_short_path() / entry_point_parsed.command;
auto entry_point_path
= get_bin_directory_short_path() / entry_point_parsed.command;
LOG_INFO << "entry point path: " << entry_point_path << std::endl;
auto files = create_python_entry_point(entry_point_path, entry_point_parsed);
#ifdef _WIN32
#ifdef _WIN32
out_json["paths_data"]["paths"].push_back(
{
{"_path", files[0]},
{"path_type", "win_python_entry_point"}
});
{ { "_path", files[0] }, { "path_type", "win_python_entry_point" } });
out_json["paths_data"]["paths"].push_back(
{
{"_path", files[1]},
{"path_type", "windows_python_entry_point_exe"}
});
{ { "_path", files[1] },
{ "path_type", "windows_python_entry_point_exe" } });
out_json["files"].push_back(files[0]);
out_json["files"].push_back(files[1]);
#else
#else
out_json["paths_data"]["paths"].push_back(
{
{"_path", files},
{"path_type", "unix_python_entry_point"}
});
{ { "_path", files }, { "path_type", "unix_python_entry_point" } });
out_json["files"].push_back(files);
#endif
#endif
}
}
}
@ -935,4 +964,4 @@ namespace mamba
UnlinkPackage ulp(m_pkg_info, m_cache_path, m_context);
return ulp.execute();
}
}
} // namespace mamba

View File

@ -10,12 +10,12 @@
#include "activation.hpp"
#include "channel.hpp"
#include "context.hpp"
#include "repo.hpp"
#include "transaction.hpp"
#include "prefix_data.hpp"
#include "subdirdata.hpp"
#include "solver.hpp"
#include "repo.hpp"
#include "shell_init.hpp"
#include "solver.hpp"
#include "subdirdata.hpp"
#include "transaction.hpp"
#include "version.hpp"
const char banner[] = R"MAMBARAW(
@ -27,9 +27,10 @@ const char banner[] = R"MAMBARAW(
/_/
)MAMBARAW";
using namespace mamba;
using namespace mamba; // NOLINT(build/namespaces)
static struct {
static struct
{
bool hook;
std::string shell_type;
std::string action;
@ -37,19 +38,22 @@ static struct {
bool stack;
} shell_options;
static struct {
static struct
{
std::vector<std::string> specs;
std::string prefix;
std::string name;
std::vector<std::string> channels;
} create_options;
static struct {
static struct
{
bool ssl_verify = true;
std::string cacert_path;
} network_options;
static struct {
static struct
{
int verbosity = 0;
bool always_yes = false;
bool quiet = false;
@ -58,32 +62,38 @@ static struct {
bool dry_run = false;
} global_options;
void init_network_parser(CLI::App* subcom)
void
init_network_parser(CLI::App* subcom)
{
subcom->add_option("--ssl_verify", network_options.ssl_verify, "Enable or disable SSL verification");
subcom->add_option(
"--ssl_verify", network_options.ssl_verify, "Enable or disable SSL verification");
subcom->add_option("--cacert_path", network_options.cacert_path, "Path for CA Certificate");
}
void init_global_parser(CLI::App* subcom)
void
init_global_parser(CLI::App* subcom)
{
subcom->add_flag("-v,--verbose", global_options.verbosity, "Enbable verbose mode (higher verbosity with multiple -v, e.g. -vvv)");
subcom->add_flag("-v,--verbose",
global_options.verbosity,
"Enbable verbose mode (higher verbosity with multiple -v, e.g. -vvv)");
subcom->add_flag("-q,--quiet", global_options.quiet, "Quiet mode (print less output)");
subcom->add_flag("-y,--yes", global_options.always_yes, "Automatically answer yes on all questions");
subcom->add_flag(
"-y,--yes", global_options.always_yes, "Automatically answer yes on all questions");
subcom->add_flag("--json", global_options.json, "Report all output as json");
subcom->add_flag("--offline", global_options.offline, "Force use cached repodata");
subcom->add_flag("--dry-run", global_options.dry_run, "Only display what would have been done");
}
void set_network_options(Context& ctx)
void
set_network_options(Context& ctx)
{
std::array<std::string, 6> cert_locations {
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
"/etc/ssl/ca-bundle.pem", // OpenSUSE
"/etc/pki/tls/cacert.pem", // OpenELEC
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
"/etc/ssl/cert.pem", // Alpine Linux
std::array<std::string, 6> cert_locations{
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
"/etc/ssl/ca-bundle.pem", // OpenSUSE
"/etc/pki/tls/cacert.pem", // OpenELEC
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
"/etc/ssl/cert.pem", // Alpine Linux
};
// ssl verify can be either an empty string (regular SSL verification),
@ -114,7 +124,8 @@ void set_network_options(Context& ctx)
}
}
void set_global_options(Context& ctx)
void
set_global_options(Context& ctx)
{
ctx.set_verbosity(global_options.verbosity);
ctx.quiet = global_options.quiet;
@ -124,31 +135,40 @@ void set_global_options(Context& ctx)
ctx.dry_run = global_options.dry_run;
}
void init_channel_parser(CLI::App* subcom)
void
init_channel_parser(CLI::App* subcom)
{
subcom->add_option("-c,--channel", create_options.channels) \
->type_size(1, 1) \
->allow_extra_args(false);
subcom->add_option("-c,--channel", create_options.channels)
->type_size(1, 1)
->allow_extra_args(false);
}
void set_channels(Context& ctx)
void
set_channels(Context& ctx)
{
ctx.channels = create_options.channels;
}
void init_shell_parser(CLI::App* subcom)
void
init_shell_parser(CLI::App* subcom)
{
subcom->add_option("-s,--shell", shell_options.shell_type, "A shell type (bash, fish, posix, powershell, xonsh)");
subcom->add_option("--stack", shell_options.stack,
"Stack the environment being activated on top of the previous active environment, "
"rather replacing the current active environment with a new one. Currently, "
"only the PATH environment variable is stacked. "
"This may be enabled implicitly by the 'auto_stack' configuration variable."
);
subcom->add_option("-s,--shell",
shell_options.shell_type,
"A shell type (bash, fish, posix, powershell, xonsh)");
subcom->add_option("--stack",
shell_options.stack,
"Stack the environment being activated on top of the "
"previous active environment, "
"rather replacing the current active environment with a "
"new one. Currently, "
"only the PATH environment variable is stacked. "
"This may be enabled implicitly by the 'auto_stack' "
"configuration variable.");
subcom->add_option("action", shell_options.action, "activate, deactivate or hook");
// TODO add custom validator here!
subcom->add_option("-p,--prefix", shell_options.prefix,
subcom->add_option("-p,--prefix",
shell_options.prefix,
"The root prefix to configure (for init and hook), and the prefix "
"to activate for activate, either by name or by path");
@ -172,7 +192,8 @@ void init_shell_parser(CLI::App* subcom)
}
else
{
std::cout << "Currently allowed values are: bash, zsh, cmd.exe & powershell" << std::endl;
std::cout << "Currently allowed values are: bash, zsh, cmd.exe & powershell"
<< std::endl;
exit(1);
}
if (shell_options.action == "init")
@ -208,24 +229,28 @@ void init_shell_parser(CLI::App* subcom)
});
}
void install_specs(const std::vector<std::string>& specs, bool create_env = false)
void
install_specs(const std::vector<std::string>& specs, bool create_env = false)
{
auto& ctx = Context::instance();
set_global_options(ctx);
Console::print(banner);
if (ctx.root_prefix.empty())
{
std::cout << "You have not set a $MAMBA_ROOT_PREFIX.\nEither set the MAMBA_ROOT_PREFIX environment variable, or use\n micromamba shell init ... \nto initialize your shell, then restart or source the contents of the shell init script.\n";
std::cout << "You have not set a $MAMBA_ROOT_PREFIX.\nEither set the "
"MAMBA_ROOT_PREFIX environment variable, or use\n micromamba "
"shell init ... \nto initialize your shell, then restart or "
"source the contents of the shell init script.\n";
exit(1);
}
if (ctx.target_prefix.empty())
{
std::cout << "No active target prefix.\n\nRun $ micromamba activate <PATH_TO_MY_ENV>\nto activate an environment.\n";
std::cout << "No active target prefix.\n\nRun $ micromamba activate "
"<PATH_TO_MY_ENV>\nto activate an environment.\n";
exit(1);
}
if (!fs::exists(ctx.target_prefix) && create_env == false)
@ -255,11 +280,9 @@ void install_specs(const std::vector<std::string>& specs, bool create_env = fals
auto& channel = make_channel(url);
std::string full_url = concat(channel.url(true), "/repodata.json");
auto sdir = std::make_shared<MSubdirData>(
concat(channel.name(), "/", channel.platform()),
full_url,
cache_dir / cache_fn_url(full_url)
);
auto sdir = std::make_shared<MSubdirData>(concat(channel.name(), "/", channel.platform()),
full_url,
cache_dir / cache_fn_url(full_url));
sdir->load();
multi_dl.add(sdir->target());
@ -282,11 +305,11 @@ void install_specs(const std::vector<std::string>& specs, bool create_env = fals
repos.push_back(repo);
}
MSolver solver(pool, {{SOLVER_FLAG_ALLOW_DOWNGRADE, 1}});
MSolver solver(pool, { { SOLVER_FLAG_ALLOW_DOWNGRADE, 1 } });
solver.add_jobs(create_options.specs, SOLVER_INSTALL);
solver.solve();
mamba::MultiPackageCache package_caches({ctx.root_prefix / "pkgs"});
mamba::MultiPackageCache package_caches({ ctx.root_prefix / "pkgs" });
mamba::MTransaction trans(solver, package_caches);
if (ctx.json)
@ -295,11 +318,15 @@ void install_specs(const std::vector<std::string>& specs, bool create_env = fals
}
// TODO this is not so great
std::vector<MRepo*> repo_ptrs;
for (auto& r : repos) { repo_ptrs.push_back(&r); }
for (auto& r : repos)
{
repo_ptrs.push_back(&r);
}
std::cout << std::endl;
bool yes = trans.prompt(ctx.root_prefix / "pkgs", repo_ptrs);
if (!yes) exit(0);
if (!yes)
exit(0);
if (create_env && !Context::instance().dry_run)
{
@ -311,7 +338,8 @@ void install_specs(const std::vector<std::string>& specs, bool create_env = fals
trans.execute(prefix_data, ctx.root_prefix / "pkgs");
}
void init_install_parser(CLI::App* subcom)
void
init_install_parser(CLI::App* subcom)
{
subcom->add_option("specs", create_options.specs, "Specs to install into the new environment");
init_network_parser(subcom);
@ -325,7 +353,8 @@ void init_install_parser(CLI::App* subcom)
});
}
void init_create_parser(CLI::App* subcom)
void
init_create_parser(CLI::App* subcom)
{
subcom->add_option("specs", create_options.specs, "Specs to install into the new environment");
subcom->add_option("-p,--prefix", create_options.prefix, "Path to the Prefix");
@ -352,14 +381,16 @@ void init_create_parser(CLI::App* subcom)
});
}
std::string version()
std::string
version()
{
return mamba_version;
}
int main(int argc, char** argv)
int
main(int argc, char** argv)
{
CLI::App app{std::string(banner) + "\nVersion: " + version() + "\n"};
CLI::App app{ std::string(banner) + "\nVersion: " + version() + "\n" };
auto print_version = [](int count) {
std::cout << version() << std::endl;
@ -373,7 +404,8 @@ int main(int argc, char** argv)
CLI::App* create_subcom = app.add_subcommand("create", "Create new environment");
init_create_parser(create_subcom);
CLI::App* install_subcom = app.add_subcommand("install", "Install packages in active environment");
CLI::App* install_subcom
= app.add_subcommand("install", "Install packages in active environment");
init_install_parser(install_subcom);
// just for the help text

View File

@ -5,6 +5,7 @@
// The full license is in the file LICENSE, distributed with this software.
#include "match_spec.hpp"
#include "output.hpp"
#include "url.hpp"
#include "util.hpp"
@ -33,24 +34,22 @@ namespace mamba
{
std::size_t pm1 = pos - 1;
char d = s[pm1];
if (d == '=' || d == '!' || d == '|' ||
d == ',' || d == '<' || d == '>' || d == '~')
if (d == '=' || d == '!' || d == '|' || d == ',' || d == '<' || d == '>'
|| d == '~')
{
std::string tmp = s;
replace_all(tmp, " ", "");
return { tmp , "" };
return { tmp, "" };
}
}
// c is either ' ' or pm1 is none of the forbidden chars
std::string v = s.substr(0, pos),
b = s.substr(pos + 1);
std::string v = s.substr(0, pos), b = s.substr(pos + 1);
replace_all(v, " ", "");
replace_all(b, " ", "");
return { v, b };
}
};
}
void MatchSpec::parse()
{
@ -74,8 +73,7 @@ namespace mamba
LOG_INFO << "Got a package file: " << spec_str << std::endl;
}
auto extract_kv = [&spec_str](const std::string& kv_string, auto& map)
{
auto extract_kv = [&spec_str](const std::string& kv_string, auto& map) {
static std::regex kv_re("([a-zA-Z0-9_-]+?)=([\"\']?)([^\'\"]*?)(\\2)(?:[\'\", ]|$)");
std::cmatch kv_match;
const char* text_iter = kv_string.c_str();
@ -153,7 +151,8 @@ namespace mamba
// if 'subdir' in brackets:
// subdir = brackets.pop('subdir')
// support faulty conda matchspecs such as `libblas=[build=*mkl]`, which is the repr of `libblas=*=*mkl`
// support faulty conda matchspecs such as `libblas=[build=*mkl]`, which is
// the repr of `libblas=*=*mkl`
if (spec_str.back() == '=')
{
spec_str.push_back('*');
@ -181,7 +180,8 @@ namespace mamba
{
if (version.find("[") != version.npos)
{
throw std::runtime_error("Invalid match spec: multiple bracket sections not allowed " + spec);
throw std::runtime_error(
"Invalid match spec: multiple bracket sections not allowed " + spec);
}
version = std::string(strip(version));
@ -309,10 +309,8 @@ namespace mamba
std::vector<std::string> brackets;
bool version_exact = false;
auto is_complex_relation = [](const std::string& s)
{
return s.find_first_of("><$^|,") != s.npos;
};
auto is_complex_relation
= [](const std::string& s) { return s.find_first_of("><$^|,") != s.npos; };
if (!version.empty())
{
@ -398,4 +396,4 @@ namespace mamba
}
return res.str();
}
}
} // namespace mamba

View File

@ -13,18 +13,21 @@
#include <algorithm>
#include <cstdlib>
#include "thirdparty/termcolor.hpp"
#include "output.hpp"
#include "util.hpp"
#include "url.hpp"
#include "thirdparty/termcolor.hpp"
#include "thread_utils.hpp"
#include "url.hpp"
#include "util.hpp"
namespace mamba
{
std::ostream& write_duration(std::ostream &os, std::chrono::nanoseconds ns)
std::ostream& write_duration(std::ostream& os, std::chrono::nanoseconds ns)
{
using namespace std::chrono;
using std::chrono::duration;
using std::chrono::duration_cast;
using std::chrono::hours;
using std::chrono::minutes;
using std::chrono::seconds;
using days = duration<int, std::ratio<86400>>;
char fill = os.fill();
@ -51,16 +54,16 @@ namespace mamba
int get_console_width()
{
#ifndef _WIN32
#ifndef _WIN32
struct winsize w;
ioctl(0, TIOCGWINSZ, &w);
return w.ws_col;
#else
#else
CONSOLE_SCREEN_BUFFER_INFO coninfo;
auto res = GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
return coninfo.dwSize.X;
#endif
#endif
return -1;
}
@ -82,7 +85,7 @@ namespace mamba
std::ostream& ProgressScaleWriter::write(std::ostream& os, std::size_t progress) const
{
int pos = int(progress * m_bar_width / 100.0);
int pos = static_cast<int>(progress * m_bar_width / 100.0);
for (int i = 0; i < m_bar_width; ++i)
{
if (i < pos)
@ -106,7 +109,8 @@ namespace mamba
***************/
ProgressBar::ProgressBar(const std::string& prefix)
: m_prefix(prefix), m_start_time_saved(false)
: m_prefix(prefix)
, m_start_time_saved(false)
{
}
@ -171,16 +175,18 @@ namespace mamba
pf << m_postfix;
auto fpf = pf.str();
int width = get_console_width();
width = (width == -1) ? 20 : (std::min)(int(width - (m_prefix.size() + 4) - fpf.size()), 20);
width = (width == -1)
? 20
: (std::min)(static_cast<int>(width - (m_prefix.size() + 4) - fpf.size()), 20);
if (!m_activate_bob)
{
ProgressScaleWriter w{width, "=", ">", " "};
ProgressScaleWriter w{ width, "=", ">", " " };
w.write(std::cout, m_progress);
}
else
{
auto pos = int(m_progress * width / 100.0);
auto pos = static_cast<int>(m_progress * width / 100.0);
for (int i = 0; i < width; ++i)
{
if (i == pos - 1)
@ -274,7 +280,7 @@ namespace mamba
namespace printers
{
constexpr const char* green = "\033[32m";
constexpr const char* red = "\033[31m";
constexpr const char* red = "\033[31m";
constexpr const char* reset = "\033[00m";
Table::Table(const std::vector<FormattedString>& header)
@ -297,7 +303,8 @@ namespace mamba
m_table.push_back(r);
}
void Table::add_rows(const std::string& header, const std::vector<std::vector<FormattedString>>& rs)
void Table::add_rows(const std::string& header,
const std::vector<std::vector<FormattedString>>& rs)
{
m_table.push_back({ header });
@ -307,10 +314,12 @@ namespace mamba
std::ostream& Table::print(std::ostream& out)
{
if (m_table.size() == 0) return out;
if (m_table.size() == 0)
return out;
std::size_t n_col = m_header.size();
if (m_align.size() == 0) m_align = std::vector<alignment>(n_col, alignment::left);
if (m_align.size() == 0)
m_align = std::vector<alignment>(n_col, alignment::left);
std::vector<std::size_t> cell_sizes(n_col);
for (size_t i = 0; i < n_col; ++i)
@ -318,14 +327,16 @@ namespace mamba
for (size_t i = 0; i < m_table.size(); ++i)
{
if (m_table[i].size() == 1) continue;
if (m_table[i].size() == 1)
continue;
for (size_t j = 0; j < m_table[i].size(); ++j)
cell_sizes[j] = std::max(cell_sizes[j], m_table[i][j].size());
}
if (m_padding.size())
{
for (std::size_t i = 0; i < n_col; ++i) cell_sizes[i];
for (std::size_t i = 0; i < n_col; ++i)
cell_sizes[i];
}
else
{
@ -335,16 +346,20 @@ namespace mamba
std::size_t total_length = std::accumulate(cell_sizes.begin(), cell_sizes.end(), 0);
total_length = std::accumulate(m_padding.begin(), m_padding.end(), total_length);
auto print_row = [this, &cell_sizes, &out](const std::vector<FormattedString>& row)
{
auto print_row = [this, &cell_sizes, &out](const std::vector<FormattedString>& row) {
for (size_t j = 0; j < row.size(); ++j)
{
if (row[j].flag != format::none)
{
if (static_cast<std::size_t>(row[j].flag) & static_cast<std::size_t>(format::red)) out << termcolor::red;
if (static_cast<std::size_t>(row[j].flag) & static_cast<std::size_t>(format::green)) out << termcolor::green;
if (static_cast<std::size_t>(row[j].flag) & static_cast<std::size_t>(format::yellow)) out << termcolor::yellow;
if (static_cast<std::size_t>(row[j].flag)
& static_cast<std::size_t>(format::red))
out << termcolor::red;
if (static_cast<std::size_t>(row[j].flag)
& static_cast<std::size_t>(format::green))
out << termcolor::green;
if (static_cast<std::size_t>(row[j].flag)
& static_cast<std::size_t>(format::yellow))
out << termcolor::yellow;
}
if (this->m_align[j] == alignment::left)
{
@ -366,11 +381,11 @@ namespace mamba
print_row(m_header);
#ifdef _WIN32
#define MAMBA_TABLE_DELIM "-"
#else
#define MAMBA_TABLE_DELIM "─"
#endif
#ifdef _WIN32
#define MAMBA_TABLE_DELIM "-"
#else
#define MAMBA_TABLE_DELIM "─"
#endif
out << "\n";
for (size_t i = 0; i < total_length + m_padding[0]; ++i)
@ -384,11 +399,12 @@ namespace mamba
if (m_table[i].size() == 1)
{
// print header
if (i != 0) std::cout << "\n";
if (i != 0)
std::cout << "\n";
for (int x = 0; x < m_padding[0]; ++x)
{
out << ' ';
out << ' ';
}
out << m_table[i][0].s;
@ -407,7 +423,7 @@ namespace mamba
}
return out;
}
}
} // namespace printers
/*****************
* ConsoleStream *
@ -447,13 +463,13 @@ namespace mamba
if (!(Context::instance().quiet || Context::instance().json) || force_print)
{
// print above the progress bars
if (Console::instance().m_progress_started && Console::instance().m_active_progress_bars.size())
if (Console::instance().m_progress_started
&& Console::instance().m_active_progress_bars.size())
{
{
const std::lock_guard<std::mutex> lock(instance().m_mutex);
const auto& ps = instance().m_active_progress_bars.size();
std::cout << cursor::up(ps) << cursor::erase_line()
<< str << std::endl;
std::cout << cursor::up(ps) << cursor::erase_line() << str << std::endl;
if (!Console::instance().skip_progress_bars())
{
@ -532,15 +548,20 @@ namespace mamba
{
std::lock_guard<std::mutex> lock(instance().m_mutex);
if (Context::instance().no_progress_bars && !(Context::instance().quiet || Context::instance().json))
if (Context::instance().no_progress_bars
&& !(Context::instance().quiet || Context::instance().json))
{
std::cout << m_progress_bars[idx]->prefix() << " " << msg << "\n";
}
auto it = std::find(m_active_progress_bars.begin(), m_active_progress_bars.end(), m_progress_bars[idx].get());
if (it == m_active_progress_bars.end() || Context::instance().quiet || Context::instance().json)
auto it = std::find(m_active_progress_bars.begin(),
m_active_progress_bars.end(),
m_progress_bars[idx].get());
if (it == m_active_progress_bars.end() || Context::instance().quiet
|| Context::instance().json)
{
// if no_progress_bars is true, should return here as no progress bars are active
// if no_progress_bars is true, should return here as no progress bars are
// active
return;
}
@ -574,7 +595,9 @@ namespace mamba
std::cout << cursor::up(cursor_up);
}
auto it = std::find(m_active_progress_bars.begin(), m_active_progress_bars.end(), m_progress_bars[idx].get());
auto it = std::find(m_active_progress_bars.begin(),
m_active_progress_bars.end(),
m_progress_bars[idx].get());
if (it == m_active_progress_bars.end())
{
m_active_progress_bars.push_back(m_progress_bars[idx].get());
@ -609,7 +632,8 @@ namespace mamba
bool Console::skip_progress_bars() const
{
return Context::instance().quiet || Context::instance().json || Context::instance().no_progress_bars;
return Context::instance().quiet || Context::instance().json
|| Context::instance().no_progress_bars;
}
/*****************
@ -624,9 +648,7 @@ namespace mamba
char sep = '/';
#endif
size_t pos = file.rfind(sep);
return pos != std::string::npos ?
file.substr(pos + 1, std::string::npos) :
file;
return pos != std::string::npos ? file.substr(pos + 1, std::string::npos) : file;
}
MessageLogger::MessageLogger(const char* file, int line, LogSeverity severity)
@ -645,26 +667,29 @@ namespace mamba
return;
}
switch(m_severity)
switch (m_severity)
{
case LogSeverity::fatal:
Console::stream() << "\033[1;35m" << "FATAL " << m_stream.str() << "\033[0m";
break;
case LogSeverity::error:
Console::stream() << "\033[1;31m" << "ERROR " << m_stream.str() << "\033[0m";
break;
case LogSeverity::warning:
Console::stream() << "\033[1;33m" << "WARNING " << m_stream.str() << "\033[0m";
break;
case LogSeverity::info:
Console::stream() << "INFO " << m_stream.str();
break;
case LogSeverity::debug:
Console::stream() << "DEBUG " << m_stream.str();
break;
default:
Console::stream() << "UNKOWN " << m_stream.str();
break;
case LogSeverity::fatal:
Console::stream() << "\033[1;35m"
<< "FATAL " << m_stream.str() << "\033[0m";
break;
case LogSeverity::error:
Console::stream() << "\033[1;31m"
<< "ERROR " << m_stream.str() << "\033[0m";
break;
case LogSeverity::warning:
Console::stream() << "\033[1;33m"
<< "WARNING " << m_stream.str() << "\033[0m";
break;
case LogSeverity::info:
Console::stream() << "INFO " << m_stream.str();
break;
case LogSeverity::debug:
Console::stream() << "DEBUG " << m_stream.str();
break;
default:
Console::stream() << "UNKOWN " << m_stream.str();
break;
}
if (m_severity == LogSeverity::fatal)
@ -698,7 +723,8 @@ namespace mamba
return j;
}
// write all the key/value pairs of a JSON object into the current entry, which is then a JSON object
// write all the key/value pairs of a JSON object into the current entry, which
// is then a JSON object
void JsonLogger::json_write(const nlohmann::json& j)
{
if (Context::instance().json)
@ -747,4 +773,4 @@ namespace mamba
if (Context::instance().json)
json_hier.erase(json_hier.rfind('/'));
}
}
} // namespace mamba

View File

@ -4,11 +4,11 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "nlohmann/json.hpp"
#include "validate.hpp"
#include "package_cache.hpp"
#include "nlohmann/json.hpp"
#include "package_handling.hpp"
#include "validate.hpp"
namespace mamba
{
@ -23,12 +23,14 @@ namespace mamba
{
LOG_INFO << "Attempt to create package cache directory " << m_pkgs_dir;
bool sudo_safe = path::starts_with_home(m_pkgs_dir);
path::touch(m_pkgs_dir / PACKAGE_CACHE_MAGIC_FILE, sudo_safe, /*mkdir*/true);
path::touch(m_pkgs_dir / PACKAGE_CACHE_MAGIC_FILE,
sudo_safe,
/*mkdir*/ true);
// TODO why magic string "urls" here? is it necessary?
path::touch(m_pkgs_dir / "urls", sudo_safe);
return true;
}
catch(...)
catch (...)
{
// TODO better error handling
LOG_ERROR << "cannot create package cache directory " << m_pkgs_dir;
@ -55,8 +57,7 @@ namespace mamba
return m_pkgs_dir;
}
PackageCacheData
PackageCacheData::first_writable(const std::vector<fs::path>* pkgs_dirs)
PackageCacheData PackageCacheData::first_writable(const std::vector<fs::path>* pkgs_dirs)
{
const std::vector<fs::path>* dirs = pkgs_dirs ? pkgs_dirs : &Context::instance().pkgs_dirs;
for (const auto& dir : (*dirs))
@ -115,7 +116,7 @@ namespace mamba
return m_valid_cache[pkg];
}
assert (!s.fn.empty());
assert(!s.fn.empty());
// TODO move entire cache checking logic here (including md5 sum check)
bool valid = false;
if (fs::exists(m_pkgs_dir / s.fn))
@ -129,7 +130,8 @@ namespace mamba
}
else if (fs::exists(m_pkgs_dir / strip_package_extension(s.fn)))
{
auto repodata_record_path = m_pkgs_dir / strip_package_extension(s.fn) / "info" / "repodata_record.json";
auto repodata_record_path
= m_pkgs_dir / strip_package_extension(s.fn) / "info" / "repodata_record.json";
if (fs::exists(repodata_record_path))
{
try
@ -143,7 +145,9 @@ namespace mamba
valid = valid && repodata_record["url"].get<std::string>() == s.url;
if (!valid)
{
LOG_WARNING << "Found directory with same name, but different size, channel, url or checksum " << repodata_record_path;
LOG_WARNING << "Found directory with same name, but different size, "
"channel, url or checksum "
<< repodata_record_path;
}
}
catch (...)
@ -193,8 +197,9 @@ namespace mamba
{
for (auto& c : m_caches)
{
if (c.query(s)) return true;
if (c.query(s))
return true;
}
return false;
}
}
} // namespace mamba

View File

@ -4,24 +4,23 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <sstream>
#include "package_handling.hpp"
#include <archive.h>
#include <archive_entry.h>
#include "util.hpp"
#include "nlohmann/json.hpp"
#include <sstream>
#include "package_handling.hpp"
#include "nlohmann/json.hpp"
#include "output.hpp"
#include "thread_utils.hpp"
#include "util.hpp"
namespace mamba
{
class extraction_guard
{
public:
explicit extraction_guard(const fs::path& file)
: m_file(file)
{
@ -42,14 +41,13 @@ namespace mamba
extraction_guard& operator=(extraction_guard&&) = delete;
private:
const fs::path& m_file;
};
static int copy_data(archive *ar, archive *aw)
static int copy_data(archive* ar, archive* aw)
{
int r;
const void *buff;
const void* buff;
size_t size;
la_int64_t offset;
@ -86,9 +84,9 @@ namespace mamba
}
fs::current_path(destination);
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
struct archive* a;
struct archive* ext;
struct archive_entry* entry;
int flags;
int r;
@ -164,7 +162,9 @@ namespace mamba
fs::current_path(prev_path);
}
void extract_conda(const fs::path& file, const fs::path& dest_dir, const std::vector<std::string>& parts)
void extract_conda(const fs::path& file,
const fs::path& dest_dir,
const std::vector<std::string>& parts)
{
TemporaryDirectory tdir;
extract_archive(file, tdir);
@ -252,4 +252,4 @@ namespace mamba
throw std::runtime_error("Unknown file format (" + std::string(file) + ")");
}
}
}
} // namespace mamba

View File

@ -4,20 +4,20 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "package_info.hpp"
#include <functional>
#include <map>
#include "package_info.hpp"
#include "util.hpp"
#include "output.hpp"
#include "util.hpp"
namespace mamba
{
namespace
{
template <class T>
std::string get_package_info_field(const PackageInfo&,
T PackageInfo::*field);
std::string get_package_info_field(const PackageInfo&, T PackageInfo::*field);
template <>
std::string get_package_info_field<std::string>(const PackageInfo& pkg,
@ -36,8 +36,7 @@ namespace mamba
template <class T>
PackageInfo::field_getter build_field_getter(T PackageInfo::*field)
{
using namespace std::placeholders;
return std::bind(get_package_info_field<T>, _1, field);
return std::bind(get_package_info_field<T>, std::placeholders::_1, field);
}
using field_getter_map = std::map<std::string, PackageInfo::field_getter>;
@ -64,7 +63,7 @@ namespace mamba
static field_getter_map m = build_field_getter_map();
return m;
}
}
} // namespace
PackageInfo::field_getter PackageInfo::get_field_getter(const std::string& name)
{
@ -79,15 +78,17 @@ namespace mamba
PackageInfo::compare_fun PackageInfo::less(const std::string& member)
{
auto getter = get_field_getter(member);
return [getter](const PackageInfo& lhs, const PackageInfo& rhs)
{ return getter(lhs) < getter(rhs); };
return [getter](const PackageInfo& lhs, const PackageInfo& rhs) {
return getter(lhs) < getter(rhs);
};
}
PackageInfo::compare_fun PackageInfo::equal(const std::string& member)
{
auto getter = get_field_getter(member);
return [getter](const PackageInfo& lhs, const PackageInfo& rhs)
{ return getter(lhs) == getter(rhs); };
return [getter](const PackageInfo& lhs, const PackageInfo& rhs) {
return getter(lhs) == getter(rhs);
};
}
PackageInfo::PackageInfo(Solvable* s)
@ -118,7 +119,8 @@ namespace mamba
}
else
{
channel = s->repo->name; // note this can and should be <unknown> when e.g. installing from a tarball
channel = s->repo->name; // note this can and should be <unknown> when e.g.
// installing from a tarball
}
url = channel + "/" + check_char(solvable_lookup_str(s, SOLVABLE_MEDIAFILE));
@ -155,7 +157,7 @@ namespace mamba
PackageInfo::PackageInfo(nlohmann::json&& j)
{
using namespace std::string_literals;
using namespace std::string_literals; // NOLINT(build/namespaces)
assign_or(j, "name", name, ""s);
assign_or(j, "version", version, ""s);
assign_or(j, "channel", channel, ""s);
@ -182,9 +184,14 @@ namespace mamba
{
}
PackageInfo::PackageInfo(const std::string& n, const std::string& v,
const std::string b, std::size_t bn)
: name(n), version(v), build_string(b), build_number(bn)
PackageInfo::PackageInfo(const std::string& n,
const std::string& v,
const std::string b,
std::size_t bn)
: name(n)
, version(v)
, build_string(b)
, build_number(bn)
{
}
@ -222,4 +229,4 @@ namespace mamba
// TODO channel contains subdir right now?!
return concat(channel, "::", name, "-", version, "-", build_string);
}
}
} // namespace mamba

View File

@ -6,17 +6,18 @@
#include "package_paths.hpp"
#include "util.hpp"
#include <string>
#include <map>
#include <set>
#include <string>
#include "util.hpp"
namespace mamba
{
std::map<std::string, PrefixFileParse> read_has_prefix(const fs::path& path)
{
// reads `has_prefix` file and return dict mapping filepaths to tuples(placeholder, FileMode)
// A line in `has_prefix` contains one of
// reads `has_prefix` file and return dict mapping filepaths to
// tuples(placeholder, FileMode) A line in `has_prefix` contains one of
// * filepath
// * placeholder mode filepath
// mode values are one of
@ -31,17 +32,18 @@ namespace mamba
}
for (auto& l : read_lines(path))
{
// TODO: make sure that strings that are quoted are still split correctly
// e.g. when a file path contains a space...
auto s = split(l, " ");
if (s.size() == 1)
{
res[s[0]] = PrefixFileParse{concat(PREFIX_PLACEHOLDER_1, PREFIX_PLACEHOLDER_2), "text", s[0]};
res[s[0]] = PrefixFileParse{ concat(PREFIX_PLACEHOLDER_1, PREFIX_PLACEHOLDER_2),
"text",
s[0] };
}
else if (s.size() == 3)
{
res[s[2]] = PrefixFileParse{s[0], s[1], s[2]};
res[s[2]] = PrefixFileParse{ s[0], s[1], s[2] };
}
else
{
@ -75,8 +77,7 @@ namespace mamba
auto info_dir = directory / "info";
auto paths_json_path = info_dir / "paths.json";
auto parse_file_mode = [](nlohmann::json& j) -> FileMode
{
auto parse_file_mode = [](nlohmann::json& j) -> FileMode {
if (j.find("file_mode") != j.end())
{
// check if "text" or "binary"
@ -92,8 +93,7 @@ namespace mamba
return FileMode::UNDEFINED;
};
auto parse_path_type = [](nlohmann::json& j) -> PathType
{
auto parse_path_type = [](nlohmann::json& j) -> PathType {
if (j.find("path_type") != j.end())
{
// TODO find a DIRECTORY path type
@ -164,7 +164,8 @@ namespace mamba
if (has_prefix_files.find(f) != has_prefix_files.end())
{
p.prefix_placeholder = has_prefix_files[f].placeholder;
p.file_mode = has_prefix_files[f].file_mode[0] == 't' ? FileMode::TEXT : FileMode::BINARY;
p.file_mode = has_prefix_files[f].file_mode[0] == 't' ? FileMode::TEXT
: FileMode::BINARY;
}
if (no_link.find(f) != no_link.end())
{
@ -183,4 +184,4 @@ namespace mamba
}
return res;
}
}
} // namespace mamba

View File

@ -5,6 +5,7 @@
// The full license is in the file LICENSE, distributed with this software.
#include "pool.hpp"
#include "output.hpp"
namespace mamba
@ -39,4 +40,4 @@ namespace mamba
{
return m_pool;
}
}
} // namespace mamba

View File

@ -5,6 +5,7 @@
// The full license is in the file LICENSE, distributed with this software.
#include "prefix_data.hpp"
#include "output.hpp"
namespace mamba
@ -20,7 +21,7 @@ namespace mamba
auto conda_meta_dir = m_prefix_path / "conda-meta";
if (lexists(conda_meta_dir))
{
for(auto& p: fs::directory_iterator(conda_meta_dir))
for (auto& p : fs::directory_iterator(conda_meta_dir))
{
if (ends_with(p.path().c_str(), ".json"))
{
@ -52,6 +53,6 @@ namespace mamba
nlohmann::json j;
infile >> j;
auto prec = PackageInfo(std::move(j));
m_package_records.insert({prec.name, std::move(prec)});
m_package_records.insert({ prec.name, std::move(prec) });
}
}
} // namespace mamba

View File

@ -7,29 +7,29 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "util.hpp"
#include "solver.hpp"
#include "channel.hpp"
#include "context.hpp"
#include "pool.hpp"
#include "transaction.hpp"
#include "repo.hpp"
#include "prefix_data.hpp"
#include "query.hpp"
#include "repo.hpp"
#include "solver.hpp"
#include "subdirdata.hpp"
#include "context.hpp"
#include "channel.hpp"
#include "transaction.hpp"
#include "url.hpp"
#include "util.hpp"
namespace py = pybind11;
PYBIND11_MODULE(mamba_api, m) {
PYBIND11_MODULE(mamba_api, m)
{
using namespace mamba;
py::class_<ghc::filesystem::path>(m, "Path")
.def(py::init<std::string>())
.def("__repr__", [](ghc::filesystem::path& self) -> std::string {
return std::string("ghc::filesystem::path[") + std::string(self) + "]";
})
;
});
py::implicitly_convertible<std::string, ghc::filesystem::path>();
py::register_exception<mamba_error>(m, "MambaNativeException");
@ -37,13 +37,11 @@ PYBIND11_MODULE(mamba_api, m) {
py::class_<MPool>(m, "Pool")
.def(py::init<>())
.def("set_debuglevel", &MPool::set_debuglevel)
.def("create_whatprovides", &MPool::create_whatprovides)
;
.def("create_whatprovides", &MPool::create_whatprovides);
py::class_<MultiPackageCache>(m, "MultiPackageCache")
.def(py::init<std::vector<fs::path>>())
.def("query", &MultiPackageCache::query)
;
.def("query", &MultiPackageCache::query);
py::class_<MRepo>(m, "Repo")
.def(py::init<MPool&, const std::string&, const std::string&, const std::string&>())
@ -53,8 +51,7 @@ PYBIND11_MODULE(mamba_api, m) {
.def("name", &MRepo::name)
.def("priority", &MRepo::priority)
.def("size", &MRepo::size)
.def("clear", &MRepo::clear)
;
.def("clear", &MRepo::clear);
py::class_<MTransaction>(m, "Transaction")
.def(py::init<MSolver&, MultiPackageCache&>())
@ -63,10 +60,9 @@ PYBIND11_MODULE(mamba_api, m) {
.def("print", &MTransaction::print)
.def("fetch_extract_packages", &MTransaction::fetch_extract_packages)
.def("prompt", &MTransaction::prompt)
.def("execute", [](MTransaction& self, PrefixData& target_prefix, const std::string& cache_dir) -> bool {
return self.execute(target_prefix, cache_dir);
})
;
.def("execute",
[](MTransaction& self, PrefixData& target_prefix, const std::string& cache_dir)
-> bool { return self.execute(target_prefix, cache_dir); });
py::class_<MSolver>(m, "Solver")
.def(py::init<MPool&, std::vector<std::pair<int, int>>>())
@ -78,8 +74,7 @@ PYBIND11_MODULE(mamba_api, m) {
.def("set_postsolve_flags", &MSolver::set_postsolve_flags)
.def("is_solved", &MSolver::is_solved)
.def("problems_to_str", &MSolver::problems_to_str)
.def("solve", &MSolver::solve)
;
.def("solve", &MSolver::solve);
/*py::class_<Query>(m, "Query")
.def(py::init<MPool&>())
@ -90,58 +85,53 @@ PYBIND11_MODULE(mamba_api, m) {
py::class_<Query>(m, "Query")
.def(py::init<MPool&>())
.def("find", [](const Query& q, const std::string& query)
{
if (Context::instance().json)
std::cout << q.find(query).groupby("name").json().dump(4);
else
q.find(query).groupby("name").table(std::cout);
})
.def("whoneeds", [](const Query& q, const std::string& query, bool tree)
{
//QueryResult res = q.whoneeds(query, tree);
query_result res = q.whoneeds(query, tree);
if (tree)
res.tree(std::cout);
else if (Context::instance().json)
std::cout << res.json().dump(4);
else
res.table(std::cout);
})
.def("depends", [](const Query& q, const std::string& query, bool tree)
{
query_result res = q.depends(query, tree);
if (Context::instance().json)
std::cout << res.json().dump(4);
else if (tree)
res.tree(std::cout);
else
res.table(std::cout);
});
.def("find",
[](const Query& q, const std::string& query) {
if (Context::instance().json)
std::cout << q.find(query).groupby("name").json().dump(4);
else
q.find(query).groupby("name").table(std::cout);
})
.def("whoneeds",
[](const Query& q, const std::string& query, bool tree) {
// QueryResult res = q.whoneeds(query, tree);
query_result res = q.whoneeds(query, tree);
if (tree)
res.tree(std::cout);
else if (Context::instance().json)
std::cout << res.json().dump(4);
else
res.table(std::cout);
})
.def("depends", [](const Query& q, const std::string& query, bool tree) {
query_result res = q.depends(query, tree);
if (Context::instance().json)
std::cout << res.json().dump(4);
else if (tree)
res.tree(std::cout);
else
res.table(std::cout);
});
py::class_<MSubdirData>(m, "SubdirData")
.def(py::init<const std::string&, const std::string&, const std::string&>())
.def("create_repo", &MSubdirData::create_repo)
.def("load", &MSubdirData::load)
.def("loaded", &MSubdirData::loaded)
.def("cache_path", &MSubdirData::cache_path)
;
.def("cache_path", &MSubdirData::cache_path);
m.def("cache_fn_url", &cache_fn_url);
m.def("create_cache_dir", &create_cache_dir);
py::class_<MultiDownloadTarget>(m, "DownloadTargetList")
.def(py::init<>())
.def("add", [](MultiDownloadTarget& self, MSubdirData& sub) -> void {
self.add(sub.target());
})
.def("download", &MultiDownloadTarget::download)
;
.def("add",
[](MultiDownloadTarget& self, MSubdirData& sub) -> void { self.add(sub.target()); })
.def("download", &MultiDownloadTarget::download);
py::class_<Context, std::unique_ptr<Context, py::nodelete>>(m, "Context")
.def(py::init([]() {
return std::unique_ptr<Context, py::nodelete>(&Context::instance());
}))
.def(
py::init([]() { return std::unique_ptr<Context, py::nodelete>(&Context::instance()); }))
.def_readwrite("verbosity", &Context::verbosity)
.def_readwrite("quiet", &Context::quiet)
.def_readwrite("json", &Context::json)
@ -164,13 +154,11 @@ PYBIND11_MODULE(mamba_api, m) {
.def_readwrite("envs_dirs", &Context::envs_dirs)
.def_readwrite("pkgs_dirs", &Context::pkgs_dirs)
.def("set_verbosity", &Context::set_verbosity)
.def_readwrite("channels", &Context::channels)
;
.def_readwrite("channels", &Context::channels);
py::class_<PrefixData>(m, "PrefixData")
.def(py::init<const std::string&>())
.def("load", &PrefixData::load)
;
.def("load", &PrefixData::load);
py::class_<Channel>(m, "Channel")
.def(py::init([](const std::string& value) { return &(make_channel(value)); }))
@ -181,8 +169,7 @@ PYBIND11_MODULE(mamba_api, m) {
.def_property_readonly("subdir", &Channel::platform)
.def_property_readonly("canonical_name", &Channel::canonical_name)
.def("url", &Channel::url, py::arg("with_credentials") = true)
.def("__repr__", [](const Channel& c) { return join_url(c.name(), c.platform()); })
;
.def("__repr__", [](const Channel& c) { return join_url(c.name(), c.platform()); });
m.def("get_channel_urls", &get_channel_urls);
m.def("calculate_channel_urls", &calculate_channel_urls);

View File

@ -4,22 +4,24 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <sstream>
#include "query.hpp"
extern "C"
{
#include <solv/evr.h>
}
#include <iomanip>
#include <numeric>
#include <set>
#include <sstream>
#include <stack>
#include "query.hpp"
#include "match_spec.hpp"
#include "package_info.hpp"
#include "output.hpp"
#include "package_info.hpp"
#include "util.hpp"
extern "C" {
#include <solv/evr.h>
}
namespace mamba
{
void walk_graph(query_result::dependency_graph& dep_graph,
@ -42,7 +44,7 @@ namespace mamba
Id* reqp = s->repo->idarraydata + s->requires;
Id req = *reqp;
while(req != 0)
while (req != 0)
{
Queue job, rec_solvables;
queue_init(&rec_solvables);
@ -81,7 +83,8 @@ namespace mamba
auto it = not_found.find(name);
if (it == not_found.end())
{
auto dep_id = dep_graph.add_node(PackageInfo(concat(name, " >>> NOT FOUND <<<")));
auto dep_id
= dep_graph.add_node(PackageInfo(concat(name, " >>> NOT FOUND <<<")));
dep_graph.add_edge(parent, dep_id);
not_found.insert(std::make_pair(name, dep_id));
}
@ -166,7 +169,8 @@ namespace mamba
Pool* pool = m_pool.get();
std::sort(solvables.elements, solvables.elements + solvables.count, [pool](Id a, Id b) {
Solvable* sa; Solvable* sb;
Solvable* sa;
Solvable* sb;
sa = pool_id2solvable(pool, a);
sb = pool_id2solvable(pool, b);
return (pool_evrcmp(pool, sa->evr, sb->evr, EVRCMP_COMPARE) > 0);
@ -209,7 +213,7 @@ namespace mamba
{
Solvable* latest = pool_id2solvable(m_pool.get(), solvables.elements[0]);
auto id = g.add_node(PackageInfo(latest));
std::map<Solvable*, size_t> visited = {{latest, id}};
std::map<Solvable*, size_t> visited = { { latest, id } };
reverse_walk_graph(g, id, latest, visited);
}
}
@ -253,13 +257,15 @@ namespace mamba
Solvable* s = pool_id2solvable(m_pool.get(), solvables.elements[i]);
if (pool_evrcmp_str(m_pool.get(),
pool_id2evr(m_pool.get(), s->evr),
pool_id2evr(m_pool.get(), latest->evr), 0) > 0)
pool_id2evr(m_pool.get(), latest->evr),
0)
> 0)
{
latest = s;
}
}
auto id = g.add_node(PackageInfo(latest));
std::map<Solvable*, size_t> visited = {{latest, id}};
std::map<Solvable*, size_t> visited = { { latest, id } };
std::map<std::string, size_t> not_found;
walk_graph(g, id, latest, visited, not_found, depth);
}
@ -294,39 +300,23 @@ namespace mamba
, m_ordered_pkg_list()
{
using std::swap;
auto offset_lbd = [&rhs, this](auto iter)
{
return m_dep_graph.get_node_list().begin() + (iter - rhs.m_dep_graph.get_node_list().begin());
auto offset_lbd = [&rhs, this](auto iter) {
return m_dep_graph.get_node_list().begin()
+ (iter - rhs.m_dep_graph.get_node_list().begin());
};
package_view_list tmp(rhs.m_pkg_view_list.size());
std::transform
(
rhs.m_pkg_view_list.begin(),
rhs.m_pkg_view_list.end(),
tmp.begin(),
offset_lbd
);
std::transform(
rhs.m_pkg_view_list.begin(), rhs.m_pkg_view_list.end(), tmp.begin(), offset_lbd);
swap(tmp, m_pkg_view_list);
if (!rhs.m_ordered_pkg_list.empty())
{
auto tmp(rhs.m_ordered_pkg_list);
std::for_each
(
tmp.begin(),
tmp.end(),
[offset_lbd](auto& entry)
{
std::transform
(
entry.second.begin(),
entry.second.end(),
entry.second.begin(),
offset_lbd
);
}
);
std::for_each(tmp.begin(), tmp.end(), [offset_lbd](auto& entry) {
std::transform(
entry.second.begin(), entry.second.end(), entry.second.begin(), offset_lbd);
});
swap(m_ordered_pkg_list, tmp);
}
}
@ -358,16 +348,18 @@ namespace mamba
if (!m_ordered_pkg_list.empty())
{
for (auto& entry: m_ordered_pkg_list)
for (auto& entry : m_ordered_pkg_list)
{
std::sort(entry.second.begin(), entry.second.end(),
[fun](const auto& lhs, const auto& rhs) { return fun(*lhs, *rhs); });
std::sort(entry.second.begin(),
entry.second.end(),
[fun](const auto& lhs, const auto& rhs) { return fun(*lhs, *rhs); });
}
}
else
{
std::sort(m_pkg_view_list.begin(), m_pkg_view_list.end(),
[fun](const auto& lhs, const auto& rhs) { return fun(*lhs, *rhs); });
std::sort(m_pkg_view_list.begin(),
m_pkg_view_list.end(),
[fun](const auto& lhs, const auto& rhs) { return fun(*lhs, *rhs); });
}
return *this;
@ -378,7 +370,7 @@ namespace mamba
auto fun = PackageInfo::get_field_getter(field);
if (m_ordered_pkg_list.empty())
{
for (auto& pkg: m_pkg_view_list)
for (auto& pkg : m_pkg_view_list)
{
m_ordered_pkg_list[fun(*pkg)].push_back(pkg);
}
@ -386,9 +378,9 @@ namespace mamba
else
{
ordered_package_list tmp;
for (auto& entry: m_ordered_pkg_list)
for (auto& entry : m_ordered_pkg_list)
{
for (auto& pkg: entry.second)
for (auto& pkg : entry.second)
{
std::string key = entry.first + '/' + fun(*pkg);
tmp[key].push_back(pkg);
@ -413,23 +405,26 @@ namespace mamba
out << "No entries matching \"" << m_query << "\" found";
}
printers::Table printer({"Name", "Version", "Build", "Channel"});
printers::Table printer({ "Name", "Version", "Build", "Channel" });
if (!m_ordered_pkg_list.empty())
{
for (auto& entry: m_ordered_pkg_list)
for (auto& entry : m_ordered_pkg_list)
{
for (auto& pkg: entry.second)
for (auto& pkg : entry.second)
{
printer.add_row({pkg->name, pkg->version, pkg->build_string, cut_repo_name(pkg->channel)});
printer.add_row({ pkg->name,
pkg->version,
pkg->build_string,
cut_repo_name(pkg->channel) });
}
}
}
else
{
for (const auto& pkg: m_pkg_view_list)
for (const auto& pkg : m_pkg_view_list)
{
printer.add_row({pkg->name, pkg->version, pkg->build_string, pkg->channel});
printer.add_row({ pkg->name, pkg->version, pkg->build_string, pkg->channel });
}
}
return printer.print(out);
@ -438,7 +433,6 @@ namespace mamba
class graph_printer
{
public:
using graph_type = query_result::dependency_graph;
using node_id = graph_type::node_id;
@ -480,12 +474,17 @@ namespace mamba
}
}
void tree_edge(node_id, node_id, const graph_type&) {}
void back_edge(node_id, node_id, const graph_type&) {}
void tree_edge(node_id, node_id, const graph_type&)
{
}
void back_edge(node_id, node_id, const graph_type&)
{
}
void forward_or_cross_edge(node_id, node_id to, const graph_type& g)
{
print_prefix(to);
m_out << concat("\033[2m", g.get_node_list()[to].name, " already visited", "\033[00m") << '\n';
m_out << concat("\033[2m", g.get_node_list()[to].name, " already visited", "\033[00m")
<< '\n';
}
void finish_edge(node_id from, node_id to, const graph_type& g)
@ -497,7 +496,6 @@ namespace mamba
}
private:
bool is_on_last_stack(node_id node) const
{
return !m_last_stack.empty() && m_last_stack.top() == node;
@ -505,7 +503,7 @@ namespace mamba
void print_prefix(node_id node)
{
for (const auto& token: m_prefix_stack)
for (const auto& token : m_prefix_stack)
{
m_out << token;
}
@ -528,7 +526,8 @@ namespace mamba
std::ostream& query_result::tree(std::ostream& out) const
{
bool use_graph = !m_dep_graph.get_node_list().empty() && !m_dep_graph.get_edge_list(0).empty();
bool use_graph
= !m_dep_graph.get_node_list().empty() && !m_dep_graph.get_edge_list(0).empty();
if (use_graph)
{
graph_printer printer(out);
@ -551,20 +550,13 @@ namespace mamba
{
nl::json j;
std::string query_type = m_type == QueryType::Search
? "search"
: (m_type == QueryType::Depends
? "depends"
: "whoneeds");
j["query"] = {
{"query", MatchSpec(m_query).conda_build_form()},
{"type", query_type}
};
? "search"
: (m_type == QueryType::Depends ? "depends" : "whoneeds");
j["query"] = { { "query", MatchSpec(m_query).conda_build_form() }, { "type", query_type } };
std::string msg = m_pkg_view_list.empty() ? "No entries matching \"" + m_query + "\" found" : "";
j["result"] = {
{"msg", msg},
{"status", "OK"}
};
std::string msg
= m_pkg_view_list.empty() ? "No entries matching \"" + m_query + "\" found" : "";
j["result"] = { { "msg", msg }, { "status", "OK" } };
j["result"]["pkgs"] = nlohmann::json::array();
for (size_t i = 0; i < m_pkg_view_list.size(); ++i)
@ -576,7 +568,8 @@ namespace mamba
{
bool has_root = !m_dep_graph.get_edge_list(0).empty();
j["result"]["graph_roots"] = nlohmann::json::array();
j["result"]["graph_roots"].push_back(has_root ? m_dep_graph.get_node_list()[0].json() : nl::json(m_query));
j["result"]["graph_roots"].push_back(has_root ? m_dep_graph.get_node_list()[0].json()
: nl::json(m_query));
}
return j;
}
@ -584,14 +577,11 @@ namespace mamba
void query_result::reset_pkg_view_list()
{
auto it = m_dep_graph.get_node_list().begin();
std::generate(m_pkg_view_list.begin(),
m_pkg_view_list.end(),
[&it]() { return it++; });
std::generate(m_pkg_view_list.begin(), m_pkg_view_list.end(), [&it]() { return it++; });
}
std::string query_result::get_package_repr(const PackageInfo& pkg) const
{
return pkg.version.empty() ? pkg.name : pkg.name + '[' + pkg.version + ']';
}
}
} // namespace mamba

View File

@ -5,12 +5,13 @@
// The full license is in the file LICENSE, distributed with this software.
#include "repo.hpp"
#include "package_info.hpp"
#include "output.hpp"
#include "package_info.hpp"
extern "C"
{
#include "solv/repo_write.h"
#include "solv/repo_write.h"
}
#define MAMBA_TOOL_VERSION "1.1"
@ -21,11 +22,10 @@ namespace mamba
{
const char* mamba_tool_version()
{
static char MTV[30];
const size_t bufferSize = 30;
static char MTV[bufferSize];
MTV[0] = '\0';
strcat(MTV, MAMBA_TOOL_VERSION);
strcat(MTV, "_");
strcat(MTV, solv_version);
snprintf(MTV, bufferSize, MAMBA_TOOL_VERSION, "_", solv_version);
return MTV;
}
@ -54,17 +54,19 @@ namespace mamba
{
m_repo = repo_create(pool, "installed");
int flags = 0;
Repodata *data;
Repodata* data;
data = repo_add_repodata(m_repo, flags);
for (auto& [name, record] : prefix_data.records())
{
LOG_INFO << "Adding package record to repo " << name;
Id handle = repo_add_solvable(m_repo);
Solvable *s;
Solvable* s;
s = pool_id2solvable(pool, handle);
repodata_set_str(data, handle, SOLVABLE_BUILDVERSION, std::to_string(record.build_number).c_str());
repodata_add_poolstr_array(data, handle, SOLVABLE_BUILDFLAVOR, record.build_string.c_str());
repodata_set_str(
data, handle, SOLVABLE_BUILDVERSION, std::to_string(record.build_number).c_str());
repodata_add_poolstr_array(
data, handle, SOLVABLE_BUILDFLAVOR, record.build_string.c_str());
s->name = pool_str2id(pool, record.name.c_str(), 1);
s->evr = pool_str2id(pool, record.version.c_str(), 1);
@ -95,7 +97,8 @@ namespace mamba
}
}
s->provides = repo_addid_dep(m_repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
s->provides = repo_addid_dep(
m_repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
}
LOG_INFO << "Internalizing";
repodata_internalize(data);
@ -107,9 +110,9 @@ namespace mamba
// not sure if reuse_ids is useful here
// repo will be freed with pool as well though
// maybe explicitly free pool for faster repo deletion as well
// TODO this is actually freed with the pool, and calling it here will cause segfaults.
// need to find a more clever way to do this.
// repo_free(m_repo, /*reuse_ids*/1);
// TODO this is actually freed with the pool, and calling it here will cause
// segfaults. need to find a more clever way to do this. repo_free(m_repo,
// /*reuse_ids*/1);
}
void MRepo::set_installed()
@ -178,7 +181,8 @@ namespace mamba
int ret = repo_add_solv(m_repo, fp, 0);
if (ret != 0)
{
LOG_ERROR << "Could not load .solv file, falling back to JSON" << pool_errstr(m_repo->pool);
LOG_ERROR << "Could not load .solv file, falling back to JSON"
<< pool_errstr(m_repo->pool);
}
else
{
@ -198,23 +202,27 @@ namespace mamba
int pip_added = repodata_lookup_num(repodata, SOLVID_META, pip_added_id, -1);
const char* etag = repodata_lookup_str(repodata, SOLVID_META, etag_id);
const char* mod = repodata_lookup_str(repodata, SOLVID_META, mod_id);
const char* tool_version = repodata_lookup_str(repodata, SOLVID_META, REPOSITORY_TOOLVERSION);
bool metadata_valid = !(!url || !etag || !mod || !tool_version || pip_added == -1);
const char* tool_version
= repodata_lookup_str(repodata, SOLVID_META, REPOSITORY_TOOLVERSION);
bool metadata_valid
= !(!url || !etag || !mod || !tool_version || pip_added == -1);
if (metadata_valid)
{
RepoMetadata read_metadata {
url, pip_added == 1, etag, mod
};
metadata_valid = (read_metadata == m_metadata) && (std::strcmp(tool_version, mamba_tool_version()) == 0);
RepoMetadata read_metadata{ url, pip_added == 1, etag, mod };
metadata_valid = (read_metadata == m_metadata)
&& (std::strcmp(tool_version, mamba_tool_version()) == 0);
}
LOG_INFO << "Metadata from .solv is " << (metadata_valid ? "valid" : "NOT valid");
LOG_INFO << "Metadata from .solv is "
<< (metadata_valid ? "valid" : "NOT valid");
if (!metadata_valid)
{
LOG_INFO << "solv file was written with a previous version of libsolv or mamba " <<
(tool_version != nullptr ? tool_version : "<NULL>") << ", updating it now!";
LOG_INFO << "solv file was written with a previous version of "
"libsolv or mamba "
<< (tool_version != nullptr ? tool_version : "<NULL>")
<< ", updating it now!";
}
else
{
@ -241,7 +249,8 @@ namespace mamba
int ret = repo_add_conda(m_repo, fp, 0);
if (ret != 0)
{
throw std::runtime_error("Could not read JSON repodata file (" + m_json_file + ") " + std::string(pool_errstr(m_repo->pool)));
throw std::runtime_error("Could not read JSON repodata file (" + m_json_file + ") "
+ std::string(pool_errstr(m_repo->pool)));
}
// TODO move this to a more structured approach for repodata patching?
@ -311,14 +320,14 @@ namespace mamba
}
fclose(solv_f);
repodata_free(info); // delete meta info repodata again
repodata_free(info); // delete meta info repodata again
return true;
}
bool MRepo::clear(bool reuse_ids = 1)
{
repo_free(m_repo, (int)reuse_ids);
repo_free(m_repo, static_cast<int>(reuse_ids));
m_repo = nullptr;
return true;
}
}
} // namespace mamba

View File

@ -5,14 +5,17 @@
// The full license is in the file LICENSE, distributed with this software.
#include "solver.hpp"
#include "output.hpp"
#include "util.hpp"
#include "package_info.hpp"
#include "channel.hpp"
#include "output.hpp"
#include "package_info.hpp"
#include "util.hpp"
namespace mamba
{
MSolver::MSolver(MPool& pool, const std::vector<std::pair<int, int>>& flags, const PrefixData* prefix_data)
MSolver::MSolver(MPool& pool,
const std::vector<std::pair<int, int>>& flags,
const PrefixData* prefix_data)
: m_flags(flags)
, m_is_solved(false)
, m_solver(nullptr)
@ -35,9 +38,10 @@ namespace mamba
inline bool channel_match(Solvable* s, const std::string& channel)
{
// TODO this could should be a lot better.
// TODO this might match too much (e.g. bioconda would also match bioconda-experimental etc)
// Note: s->repo->name is the URL of the repo
// TODO maybe better to check all repos, select pointers, and compare the pointer (s->repo == ptr?)
// TODO this might match too much (e.g. bioconda would also match
// bioconda-experimental etc) Note: s->repo->name is the URL of the repo
// TODO maybe better to check all repos, select pointers, and compare the
// pointer (s->repo == ptr?)
Channel& chan = make_channel(s->repo->name);
return chan.url(false).find(channel) != std::string::npos;
}
@ -60,7 +64,8 @@ namespace mamba
}
if (selected_pkgs.count == 0)
{
LOG_ERROR << "Selected channel specific (or force-reinstall) job, but package is not available from channel. Solve job will fail.";
LOG_ERROR << "Selected channel specific (or force-reinstall) job, but "
"package is not available from channel. Solve job will fail.";
}
Id d = pool_queuetowhatprovides(pool, &selected_pkgs);
queue_push2(&m_jobs, job_flag | SOLVER_SOLVABLE_ONE_OF, d);
@ -102,7 +107,9 @@ namespace mamba
MatchSpec modified_spec(ms);
if (!ms.channel.empty() || !ms.version.empty() || !ms.build.empty())
{
Console::stream() << ms.conda_build_form() << ": overriding channel, version and build from installed packages due to --force-reinstall.";
Console::stream() << ms.conda_build_form()
<< ": overriding channel, version and build from "
"installed packages due to --force-reinstall.";
ms.channel = "";
ms.version = "";
ms.build = "";
@ -111,12 +118,14 @@ namespace mamba
modified_spec.channel = selected_channel;
modified_spec.version = check_char(pool_id2str(pool, s->evr));
modified_spec.build = check_char(solvable_lookup_str(s, SOLVABLE_BUILDFLAVOR));
LOG_INFO << "Reinstall " << modified_spec.conda_build_form() << " from channel " << selected_channel;
LOG_INFO << "Reinstall " << modified_spec.conda_build_form() << " from channel "
<< selected_channel;
return add_channel_specific_job(modified_spec, job_flag);
}
}
}
Id inst_id = pool_conda_matchspec((Pool*) m_pool, ms.conda_build_form().c_str());
Id inst_id
= pool_conda_matchspec(reinterpret_cast<Pool*>(m_pool), ms.conda_build_form().c_str());
queue_push2(&m_jobs, job_flag | SOLVER_SOLVABLE_PROVIDES, inst_id);
}
@ -143,7 +152,8 @@ namespace mamba
{
if (job_flag & SOLVER_ERASE)
{
throw std::runtime_error("Cannot erase a channel-specific package. (" + job + ")");
throw std::runtime_error("Cannot erase a channel-specific package. (" + job
+ ")");
}
add_channel_specific_job(ms, job_flag);
}
@ -155,7 +165,8 @@ namespace mamba
{
// Todo remove double parsing?
LOG_INFO << "Adding job: " << ms.conda_build_form() << std::endl;
Id inst_id = pool_conda_matchspec((Pool*) m_pool, ms.conda_build_form().c_str());
Id inst_id = pool_conda_matchspec(reinterpret_cast<Pool*>(m_pool),
ms.conda_build_form().c_str());
queue_push2(&m_jobs, job_flag | SOLVER_SOLVABLE_PROVIDES, inst_id);
}
}
@ -164,19 +175,23 @@ namespace mamba
void MSolver::add_constraint(const std::string& job)
{
MatchSpec ms(job);
Id inst_id = pool_conda_matchspec((Pool*) m_pool, ms.conda_build_form().c_str());
Id inst_id
= pool_conda_matchspec(reinterpret_cast<Pool*>(m_pool), ms.conda_build_form().c_str());
queue_push2(&m_jobs, SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES, inst_id);
}
void MSolver::add_pin(const std::string& job)
{
// if we pin a package, we need to remove all packages that don't match the pin from being
// available for installation!
// This is done by adding SOLVER_LOCK to the packages, so that they are prevented from being installed
// A lock basically says: keep the state of the package. I.e. uninstalled packages stay uninstalled, installed packages stay installed.
// A lock is a hard requirement, we could also use SOLVER_FAVOR for soft requirements
// if we pin a package, we need to remove all packages that don't match the
// pin from being available for installation! This is done by adding
// SOLVER_LOCK to the packages, so that they are prevented from being
// installed A lock basically says: keep the state of the package. I.e.
// uninstalled packages stay uninstalled, installed packages stay installed.
// A lock is a hard requirement, we could also use SOLVER_FAVOR for soft
// requirements
// First we need to check if the pin is OK given the currently installed packages
// First we need to check if the pin is OK given the currently installed
// packages
Pool* pool = m_pool;
MatchSpec ms(job);
@ -188,8 +203,9 @@ namespace mamba
// LOG_ERROR << "NAME " << name;
// if (name == ms.name)
// {
// LOG_ERROR << "Found pinned package in installed packages, need to check pin now.";
// LOG_ERROR << record.version << " vs " << ms.version;
// LOG_ERROR << "Found pinned package in installed packages, need
// to check pin now."; LOG_ERROR << record.version << " vs " <<
// ms.version;
// }
// }
// }
@ -225,11 +241,12 @@ namespace mamba
Queue selected_pkgs;
queue_init(&selected_pkgs);
for (auto& id: all_solvables)
for (auto& id : all_solvables)
{
if (matching_solvables.find(id) == matching_solvables.end())
{
// the solvable is _NOT_ matched by our pinning expression! So we have to lock it to make it un-installable
// the solvable is _NOT_ matched by our pinning expression! So we have to
// lock it to make it un-installable
queue_push(&selected_pkgs, id);
}
}
@ -291,7 +308,7 @@ namespace mamba
m_is_solved = true;
LOG_WARNING << "Problem count: " << solver_problem_count(m_solver) << std::endl;
success = solver_problem_count(m_solver) == 0;
JsonLogger::instance().json_write({{"success", success}});
JsonLogger::instance().json_write({ { "success", success } });
return success;
}
@ -314,4 +331,4 @@ namespace mamba
{
return m_solver;
}
}
} // namespace mamba

View File

@ -4,12 +4,12 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "openssl/md5.h"
#include "thirdparty/filesystem.hpp"
#include "subdirdata.hpp"
#include "openssl/md5.h"
#include "output.hpp"
#include "package_cache.hpp"
#include "thirdparty/filesystem.hpp"
namespace fs = ghc::filesystem;
@ -22,22 +22,24 @@ namespace decompress
LOG_INFO << "Decompressing from " << in << " to " << out;
struct archive *a = archive_read_new();
struct archive* a = archive_read_new();
archive_read_support_filter_bzip2(a);
archive_read_support_format_raw(a);
// TODO figure out good value for this
const std::size_t BLOCKSIZE = 16384;
r = archive_read_open_filename(a, in.c_str(), BLOCKSIZE);
if (r != ARCHIVE_OK) {
if (r != ARCHIVE_OK)
{
return false;
}
struct archive_entry *entry;
struct archive_entry* entry;
std::ofstream out_file(out);
char buff[BLOCKSIZE];
std::size_t buffsize = BLOCKSIZE;
r = archive_read_next_header(a, &entry);
if (r != ARCHIVE_OK) {
if (r != ARCHIVE_OK)
{
return false;
}
@ -46,7 +48,8 @@ namespace decompress
size = archive_read_data(a, &buff, buffsize);
if (size < ARCHIVE_OK)
{
throw std::runtime_error(std::string("Could not read archive: ") + archive_error_string(a));
throw std::runtime_error(std::string("Could not read archive: ")
+ archive_error_string(a));
}
if (size == 0)
{
@ -58,11 +61,13 @@ namespace decompress
archive_read_free(a);
return true;
}
}
} // namespace decompress
namespace mamba
{
MSubdirData::MSubdirData(const std::string& name, const std::string& url, const std::string& repodata_fn)
MSubdirData::MSubdirData(const std::string& name,
const std::string& url,
const std::string& repodata_fn)
: m_loaded(false)
, m_download_complete(false)
, m_url(url)
@ -72,16 +77,19 @@ namespace mamba
{
}
fs::file_time_type::duration MSubdirData::check_cache(const fs::path& cache_file, const fs::file_time_type::clock::time_point& ref)
fs::file_time_type::duration MSubdirData::check_cache(
const fs::path& cache_file, const fs::file_time_type::clock::time_point& ref)
{
try {
try
{
auto last_write = fs::last_write_time(cache_file);
auto tdiff = ref - last_write;
return tdiff;
// auto as_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(tdiff);
// return as_seconds.count();
// auto as_seconds =
// std::chrono::duration_cast<std::chrono::duration<double>>(tdiff); return
// as_seconds.count();
}
catch(...)
catch (...)
{
// could not open the file...
return fs::file_time_type::duration::max();
@ -120,11 +128,13 @@ namespace mamba
max_age = get_cache_control_max_age(el);
}
auto cache_age_seconds = std::chrono::duration_cast<std::chrono::seconds>(cache_age).count();
auto cache_age_seconds
= std::chrono::duration_cast<std::chrono::seconds>(cache_age).count();
if ((max_age > cache_age_seconds || Context::instance().offline) && !forbid_cache())
{
// cache valid!
LOG_INFO << "Using cache " << m_url << " age in seconds: " << cache_age_seconds << " / " << max_age;
LOG_INFO << "Using cache " << m_url << " age in seconds: " << cache_age_seconds
<< " / " << max_age;
std::string prefix = m_name;
prefix.resize(PREFIX_LENGTH - 1, ' ');
Console::stream() << prefix << " Using cache";
@ -134,8 +144,10 @@ namespace mamba
// check solv cache
auto solv_age = check_cache(m_solv_fn, now);
LOG_INFO << "Solv cache age in seconds: " << std::chrono::duration_cast<std::chrono::seconds>(solv_age).count();
if (solv_age != fs::file_time_type::duration::max() && solv_age.count() <= cache_age.count())
LOG_INFO << "Solv cache age in seconds: "
<< std::chrono::duration_cast<std::chrono::seconds>(solv_age).count();
if (solv_age != fs::file_time_type::duration::max()
&& solv_age.count() <= cache_age.count())
{
LOG_INFO << "Also using .solv cache file";
m_solv_cache_valid = true;
@ -188,7 +200,8 @@ namespace mamba
{
if (m_target->result != 0 || m_target->http_status >= 400)
{
LOG_INFO << "Unable to retrieve repodata (response: " << m_target->http_status << ") for " << m_url;
LOG_INFO << "Unable to retrieve repodata (response: " << m_target->http_status
<< ") for " << m_url;
m_progress_bar.set_postfix(std::to_string(m_target->http_status) + " Failed");
m_progress_bar.set_progress(100);
m_progress_bar.mark_as_completed();
@ -198,13 +211,15 @@ namespace mamba
LOG_WARNING << "HTTP response code: " << m_target->http_status;
// Note HTTP status == 0 for files
if (m_target->http_status == 0 || m_target->http_status == 200 || m_target->http_status == 304)
if (m_target->http_status == 0 || m_target->http_status == 200
|| m_target->http_status == 304)
{
m_download_complete = true;
}
else
{
throw std::runtime_error("Unhandled HTTP code: " + std::to_string(m_target->http_status));
throw std::runtime_error("Unhandled HTTP code: "
+ std::to_string(m_target->http_status));
}
if (m_target->http_status == 304)
@ -215,9 +230,12 @@ namespace mamba
auto solv_age = check_cache(m_solv_fn, now);
fs::last_write_time(m_json_fn, now);
LOG_INFO << "Solv age: " << std::chrono::duration_cast<std::chrono::seconds>(solv_age).count()
<< ", JSON age: " << std::chrono::duration_cast<std::chrono::seconds>(cache_age).count();
if(solv_age != fs::file_time_type::duration::max() && solv_age.count() <= cache_age.count())
LOG_INFO << "Solv age: "
<< std::chrono::duration_cast<std::chrono::seconds>(solv_age).count()
<< ", JSON age: "
<< std::chrono::duration_cast<std::chrono::seconds>(cache_age).count();
if (solv_age != fs::file_time_type::duration::max()
&& solv_age.count() <= cache_age.count())
{
fs::last_write_time(m_solv_fn, now);
m_solv_cache_valid = true;
@ -262,14 +280,13 @@ namespace mamba
temp_json << m_mod_etag.dump();
// replace `}` with `,`
temp_json.seekp(-1, temp_json.cur); temp_json << ',';
temp_json.seekp(-1, temp_json.cur);
temp_json << ',';
final_file << temp_json.str();
temp_file.seekg(1);
std::copy(
std::istreambuf_iterator<char>(temp_file),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(final_file)
);
std::copy(std::istreambuf_iterator<char>(temp_file),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(final_file));
m_progress_bar.set_postfix("Done");
m_progress_bar.set_progress(100);
@ -306,7 +323,8 @@ namespace mamba
m_progress_bar = Console::instance().add_progress_bar(m_name);
m_target = std::make_unique<DownloadTarget>(m_name, m_url, m_temp_file->path());
m_target->set_progress_bar(m_progress_bar);
// if we get something _other_ than the noarch, we DO NOT throw if the file can't be retrieved
// if we get something _other_ than the noarch, we DO NOT throw if the file
// can't be retrieved
if (!ends_with(m_name, "/noarch"))
{
m_target->set_ignore_failure(true);
@ -320,7 +338,8 @@ namespace mamba
static std::regex max_age_re("max-age=(\\d+)");
std::smatch max_age_match;
bool matches = std::regex_search(val, max_age_match, max_age_re);
if (!matches) return 0;
if (!matches)
return 0;
return std::stoi(max_age_match[1]);
}
@ -332,8 +351,7 @@ namespace mamba
// "_mod": "Sat, 04 Apr 2020 03:29:49 GMT",
// "_cache_control": "public, max-age=1200"
auto extract_subjson = [](std::ifstream& s)
{
auto extract_subjson = [](std::ifstream& s) {
char next;
std::string result;
bool escaped = false;
@ -373,7 +391,7 @@ namespace mamba
result = nlohmann::json::parse(json);
return result;
}
catch(...)
catch (...)
{
LOG_WARNING << "Could not parse mod / etag header!";
return nlohmann::json();
@ -394,7 +412,8 @@ namespace mamba
std::string create_cache_dir()
{
std::string cache_dir = PackageCacheData::first_writable().get_pkgs_dir().string() + "/cache";
std::string cache_dir
= PackageCacheData::first_writable().get_pkgs_dir().string() + "/cache";
fs::create_directories(cache_dir);
#ifndef _WIN32
::chmod(cache_dir.c_str(), 02775);
@ -404,13 +423,11 @@ namespace mamba
MRepo MSubdirData::create_repo(MPool& pool)
{
RepoMetadata meta {
m_url,
Context::instance().add_pip_as_python_dependency,
m_mod_etag["_etag"],
m_mod_etag["_mod"]
};
RepoMetadata meta{ m_url,
Context::instance().add_pip_as_python_dependency,
m_mod_etag["_etag"],
m_mod_etag["_mod"] };
return MRepo(pool, m_name, cache_path(), meta);
}
}
} // namespace mamba

View File

@ -1,3 +1,8 @@
// Copyright (c) 2019, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.
#include "thread_utils.hpp"
#ifndef _WIN32
@ -8,7 +13,6 @@
namespace mamba
{
/***********************
* thread interruption *
***********************/
@ -20,10 +24,7 @@ namespace mamba
void set_default_signal_handler()
{
std::signal(SIGINT, [](int signum)
{
set_sig_interrupted();
});
std::signal(SIGINT, [](int signum) { set_sig_interrupted(); });
}
bool is_sig_interrupted() noexcept
@ -57,7 +58,7 @@ namespace mamba
std::atomic<bool> is_clean = false;
std::mutex main_mutex;
std::condition_variable main_var;
}
} // namespace
void increase_thread_count()
{
@ -140,7 +141,7 @@ namespace mamba
#ifdef _WIN32
std::function<void ()> interruption_guard::m_cleanup_function;
std::function<void()> interruption_guard::m_cleanup_function;
interruption_guard::~interruption_guard()
{
@ -180,4 +181,4 @@ namespace mamba
#endif
}
} // namespace mamba

View File

@ -4,13 +4,14 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "transaction.hpp"
#include <iostream>
#include <stack>
#include <thread>
#include "transaction.hpp"
#include "match_spec.hpp"
#include "link.hpp"
#include "match_spec.hpp"
#include "thread_utils.hpp"
namespace mamba
@ -26,7 +27,8 @@ namespace mamba
std::mutex PackageDownloadExtractTarget::extract_mutex;
PackageDownloadExtractTarget::PackageDownloadExtractTarget(const MRepo& repo, Solvable* solvable)
PackageDownloadExtractTarget::PackageDownloadExtractTarget(const MRepo& repo,
Solvable* solvable)
: m_solv(solvable)
, m_finished(false)
{
@ -80,14 +82,16 @@ namespace mamba
if (size_t(m_target->downloaded_size) != expected_size)
{
LOG_ERROR << "File not valid: file size doesn't match expectation " << m_tarball_path;
throw std::runtime_error("File not valid: file size doesn't match expectation (" + std::string(m_tarball_path) + ")");
throw std::runtime_error("File not valid: file size doesn't match expectation ("
+ std::string(m_tarball_path) + ")");
}
interruption_point();
std::string sha256_check = lookup_checksum(m_solv, SOLVABLE_CHECKSUM);
if (!sha256_check.empty() && !validate::sha256(m_tarball_path, sha256_check))
{
LOG_ERROR << "File not valid: SHA256 sum doesn't match expectation " << m_tarball_path;
throw std::runtime_error("File not valid: SHA256 sum doesn't match expectation (" + std::string(m_tarball_path) + ")");
throw std::runtime_error("File not valid: SHA256 sum doesn't match expectation ("
+ std::string(m_tarball_path) + ")");
}
else
{
@ -95,7 +99,8 @@ namespace mamba
if (!md5_check.empty() && !validate::md5(m_tarball_path, md5_check))
{
LOG_ERROR << "File not valid: MD5 sum doesn't match expectation " << m_tarball_path;
throw std::runtime_error("File not valid: MD5 sum doesn't match expectation (" + std::string(m_tarball_path) + ")");
throw std::runtime_error("File not valid: MD5 sum doesn't match expectation ("
+ std::string(m_tarball_path) + ")");
}
}
@ -116,7 +121,8 @@ namespace mamba
interruption_point();
std::stringstream final_msg;
final_msg << "Finished " << std::left << std::setw(30) << m_name << std::right << std::setw(8);
final_msg << "Finished " << std::left << std::setw(30) << m_name << std::right
<< std::setw(8);
m_progress_proxy.elapsed_time_to_stream(final_msg);
final_msg << " " << std::setw(12 + 2);
to_human_readable_filesize(final_msg, expected_size);
@ -148,7 +154,8 @@ namespace mamba
}
// todo remove cache from this interface
DownloadTarget* PackageDownloadExtractTarget::target(const fs::path& cache_path, MultiPackageCache& cache)
DownloadTarget* PackageDownloadExtractTarget::target(const fs::path& cache_path,
MultiPackageCache& cache)
{
m_cache_path = cache_path;
m_tarball_path = cache_path / m_filename;
@ -187,7 +194,8 @@ namespace mamba
bool MTransaction::filter(Solvable* s)
{
if (m_filter_type == FilterType::none) return false;
if (m_filter_type == FilterType::none)
return false;
bool spec_in_filter = m_filter_name_ids.count(s->name);
if (m_filter_type == FilterType::keep_only)
@ -200,13 +208,13 @@ namespace mamba
}
}
MTransaction::MTransaction(MSolver& solver, MultiPackageCache& cache)
: m_multi_cache(cache)
{
if (!solver.is_solved())
{
throw std::runtime_error("Cannot create transaction without calling solver.solve() first.");
throw std::runtime_error(
"Cannot create transaction without calling solver.solve() first.");
}
m_transaction = solver_create_transaction(solver);
@ -264,10 +272,10 @@ namespace mamba
if (solver.only_deps == false)
{
auto to_string_vec = [](const std::vector<MatchSpec>& vec) -> std::vector<std::string>
{
auto to_string_vec = [](const std::vector<MatchSpec>& vec) -> std::vector<std::string> {
std::vector<std::string> res;
for (const auto& el : vec) res.push_back(el.str());
for (const auto& el : vec)
res.push_back(el.str());
return res;
};
m_history_entry.update = to_string_vec(solver.install_specs());
@ -281,7 +289,7 @@ namespace mamba
if (!empty())
{
JsonLogger::instance().json_down("actions");
JsonLogger::instance().json_write({{"PREFIX", Context::instance().target_prefix}});
JsonLogger::instance().json_write({ { "PREFIX", Context::instance().target_prefix } });
}
}
@ -298,8 +306,7 @@ namespace mamba
queue_init(&classes);
queue_init(&pkgs);
int mode = SOLVER_TRANSACTION_SHOW_OBSOLETES |
SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE;
int mode = SOLVER_TRANSACTION_SHOW_OBSOLETES | SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE;
transaction_classify(m_transaction, mode, &classes);
@ -309,12 +316,12 @@ namespace mamba
cls = classes.elements[i];
// cnt = classes.elements[i + 1];
transaction_classify_pkgs(m_transaction, mode, cls, classes.elements[i + 2],
classes.elements[i + 3], &pkgs);
transaction_classify_pkgs(
m_transaction, mode, cls, classes.elements[i + 2], classes.elements[i + 3], &pkgs);
for (int j = 0; j < pkgs.count; j++)
{
Id p = pkgs.elements[j];
Solvable *s = m_transaction->pool->solvables + p;
Solvable* s = m_transaction->pool->solvables + p;
if (filter(s))
{
@ -327,9 +334,11 @@ namespace mamba
case SOLVER_TRANSACTION_UPGRADED:
case SOLVER_TRANSACTION_CHANGED:
case SOLVER_TRANSACTION_REINSTALLED:
if (cls == SOLVER_TRANSACTION_REINSTALLED && m_force_reinstall == false) break;
if (cls == SOLVER_TRANSACTION_REINSTALLED && m_force_reinstall == false)
break;
m_to_remove.push_back(s);
m_to_install.push_back(m_transaction->pool->solvables + transaction_obs_pkg(m_transaction, p));
m_to_install.push_back(m_transaction->pool->solvables
+ transaction_obs_pkg(m_transaction, p));
break;
case SOLVER_TRANSACTION_ERASE:
m_to_remove.push_back(s);
@ -354,10 +363,11 @@ namespace mamba
std::string MTransaction::find_python_version()
{
// We need to find the python version that will be there after this Transaction is finished
// in order to compile the noarch packages correctly, for example
// We need to find the python version that will be there after this
// Transaction is finished in order to compile the noarch packages correctly,
// for example
Pool* pool = m_transaction->pool;
assert (pool != nullptr);
assert(pool != nullptr);
std::string py_ver;
Id python = pool_str2id(pool, "python", 0);
@ -391,7 +401,8 @@ namespace mamba
// we need to make sure that we're not about to remove python!
for (Solvable* s : m_to_remove)
{
if (s->name == python) return "";
if (s->name == python)
return "";
}
}
return py_ver;
@ -400,7 +411,6 @@ namespace mamba
class TransactionRollback
{
public:
void record(const UnlinkPackage& unlink)
{
m_unlink_stack.push(unlink);
@ -413,13 +423,13 @@ namespace mamba
void rollback()
{
while(!m_link_stack.empty())
while (!m_link_stack.empty())
{
m_link_stack.top().undo();
m_link_stack.pop();
}
while(!m_unlink_stack.empty())
while (!m_unlink_stack.empty())
{
m_unlink_stack.top().undo();
m_unlink_stack.pop();
@ -427,7 +437,6 @@ namespace mamba
}
private:
std::stack<UnlinkPackage> m_unlink_stack;
std::stack<LinkPackage> m_link_stack;
};
@ -438,9 +447,11 @@ namespace mamba
// back to the top level if any action was required
if (!empty())
JsonLogger::instance().json_up();
JsonLogger::instance().json_write({{"dry_run", Context::instance().dry_run}, {"prefix", Context::instance().target_prefix}});
JsonLogger::instance().json_write({ { "dry_run", Context::instance().dry_run },
{ "prefix", Context::instance().target_prefix } });
if (empty())
JsonLogger::instance().json_write({{"message", "All requested packages already installed"}});
JsonLogger::instance().json_write(
{ { "message", "All requested packages already installed" } });
// finally, print the JSON
if (Context::instance().json)
Console::instance().print(JsonLogger::instance().json_log.unflatten().dump(4), true);
@ -463,7 +474,7 @@ namespace mamba
{
Id p = m_transaction->steps.elements[i];
Id ttype = transaction_type(m_transaction, p, SOLVER_TRANSACTION_SHOW_ALL);
Solvable *s = pool_id2solvable(pool, p);
Solvable* s = pool_id2solvable(pool, p);
if (filter(s))
{
@ -477,10 +488,13 @@ namespace mamba
case SOLVER_TRANSACTION_CHANGED:
case SOLVER_TRANSACTION_REINSTALLED:
{
if (ttype == SOLVER_TRANSACTION_REINSTALLED && m_force_reinstall == false) break;
if (ttype == SOLVER_TRANSACTION_REINSTALLED && m_force_reinstall == false)
break;
Solvable* s2 = m_transaction->pool->solvables + transaction_obs_pkg(m_transaction, p);
Console::stream() << "Changing " << PackageInfo(s).str() << " ==> " << PackageInfo(s2).str();
Solvable* s2
= m_transaction->pool->solvables + transaction_obs_pkg(m_transaction, p);
Console::stream()
<< "Changing " << PackageInfo(s).str() << " ==> " << PackageInfo(s2).str();
PackageInfo p_unlink(s);
PackageInfo p_link(s2);
@ -488,7 +502,6 @@ namespace mamba
up.execute();
rollback.record(up);
LinkPackage lp(p_link, fs::path(cache_dir), &m_transaction_context);
lp.execute();
rollback.record(lp);
@ -565,7 +578,8 @@ namespace mamba
}
else
{
channel = s->repo->name; // note this can and should be <unknown> when e.g. installing from a tarball
channel = s->repo->name; // note this can and should be <unknown> when
// e.g. installing from a tarball
}
to_install_structured.emplace_back(channel, mediafile, s_json);
@ -613,7 +627,8 @@ namespace mamba
}
}
bool MTransaction::fetch_extract_packages(const std::string& cache_dir, std::vector<MRepo*>& repos)
bool MTransaction::fetch_extract_packages(const std::string& cache_dir,
std::vector<MRepo*>& repos)
{
fs::path cache_path(cache_dir);
std::vector<std::unique_ptr<PackageDownloadExtractTarget>> targets;
@ -642,10 +657,7 @@ namespace mamba
multi_dl.add(targets[targets.size() - 1]->target(cache_path, m_multi_cache));
}
interruption_guard g([]()
{
Console::instance().init_multi_progress();
});
interruption_guard g([]() { Console::instance().init_multi_progress(); });
bool downloaded = multi_dl.download(true);
@ -742,10 +754,13 @@ namespace mamba
Console::print(" No specs added or removed.\n");
}
printers::Table t({"Package", "Version", "Build", "Channel", "Size"});
t.set_alignment({printers::alignment::left, printers::alignment::right, printers::alignment::left,
printers::alignment::left, printers::alignment::right});
t.set_padding({2, 2, 2, 2, 5});
printers::Table t({ "Package", "Version", "Build", "Channel", "Size" });
t.set_alignment({ printers::alignment::left,
printers::alignment::right,
printers::alignment::left,
printers::alignment::left,
printers::alignment::right });
t.set_padding({ 2, 2, 2, 2, 5 });
Queue classes, pkgs;
queue_init(&classes);
@ -757,13 +772,13 @@ namespace mamba
std::size_t total_size = 0;
auto* pool = m_transaction->pool;
auto format_row = [this, pool, &total_size](rows& r, Solvable* s, printers::format flag)
{
auto format_row = [this, pool, &total_size](rows& r, Solvable* s, printers::format flag) {
std::ptrdiff_t dlsize = solvable_lookup_num(s, SOLVABLE_DOWNLOADSIZE, -1);
printers::FormattedString dlsize_s;
if (dlsize != -1)
{
if (static_cast<std::size_t>(flag) & static_cast<std::size_t>(printers::format::yellow))
if (static_cast<std::size_t>(flag)
& static_cast<std::size_t>(printers::format::yellow))
{
dlsize_s.s = "Ignored";
}
@ -778,7 +793,8 @@ namespace mamba
to_human_readable_filesize(s, dlsize);
dlsize_s.s = s.str();
// Hacky hacky
if (static_cast<std::size_t>(flag) & static_cast<std::size_t>(printers::format::green))
if (static_cast<std::size_t>(flag)
& static_cast<std::size_t>(printers::format::green))
{
total_size += dlsize;
}
@ -797,13 +813,15 @@ namespace mamba
}
else
{
channel = s->repo->name; // note this can and should be <unknown> when e.g. installing from a tarball
channel = s->repo->name; // note this can and should be <unknown> when
// e.g. installing from a tarball
}
r.push_back({name,
printers::FormattedString(pool_id2str(pool, s->evr)),
printers::FormattedString(build_string ? build_string : ""),
printers::FormattedString(cut_repo_name(channel)), dlsize_s});
r.push_back({ name,
printers::FormattedString(pool_id2str(pool, s->evr)),
printers::FormattedString(build_string ? build_string : ""),
printers::FormattedString(cut_repo_name(channel)),
dlsize_s });
};
int mode = SOLVER_TRANSACTION_SHOW_OBSOLETES | SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE;
@ -812,13 +830,13 @@ namespace mamba
for (int i = 0; i < classes.count; i += 4)
{
cls = classes.elements[i];
transaction_classify_pkgs(m_transaction, mode, cls, classes.elements[i + 2],
classes.elements[i + 3], &pkgs);
transaction_classify_pkgs(
m_transaction, mode, cls, classes.elements[i + 2], classes.elements[i + 3], &pkgs);
for (int j = 0; j < pkgs.count; j++)
{
Id p = pkgs.elements[j];
Solvable *s = m_transaction->pool->solvables + p;
Solvable* s = m_transaction->pool->solvables + p;
if (filter(s))
{
@ -829,18 +847,28 @@ namespace mamba
{
case SOLVER_TRANSACTION_UPGRADED:
format_row(upgraded, s, printers::format::red);
format_row(upgraded, m_transaction->pool->solvables + transaction_obs_pkg(m_transaction, p), printers::format::green);
format_row(upgraded,
m_transaction->pool->solvables
+ transaction_obs_pkg(m_transaction, p),
printers::format::green);
break;
case SOLVER_TRANSACTION_CHANGED:
case SOLVER_TRANSACTION_REINSTALLED:
if (cls == SOLVER_TRANSACTION_REINSTALLED && m_force_reinstall == false) break;
if (cls == SOLVER_TRANSACTION_REINSTALLED && m_force_reinstall == false)
break;
format_row(changed, s, printers::format::red);
format_row(changed, m_transaction->pool->solvables + transaction_obs_pkg(m_transaction, p), printers::format::green);
format_row(changed,
m_transaction->pool->solvables
+ transaction_obs_pkg(m_transaction, p),
printers::format::green);
break;
case SOLVER_TRANSACTION_DOWNGRADED:
format_row(downgraded, s, printers::format::red);
format_row(downgraded, m_transaction->pool->solvables + transaction_obs_pkg(m_transaction, p), printers::format::green);
format_row(downgraded,
m_transaction->pool->solvables
+ transaction_obs_pkg(m_transaction, p),
printers::format::green);
break;
case SOLVER_TRANSACTION_ERASE:
format_row(erased, s, printers::format::red);
@ -901,4 +929,4 @@ namespace mamba
t.add_row({ summary.str() });
t.print(std::cout);
}
}
} // namespace mamba

View File

@ -19,11 +19,11 @@ namespace mamba
// supply short python version, e.g. 2.7, 3.5...
fs::path get_python_short_path(const std::string& python_version)
{
#ifdef _WIN32
#ifdef _WIN32
return "python.exe";
#else
#else
return fs::path("bin") / concat("python", python_version);
#endif
#endif
}
fs::path get_python_site_packages_short_path(const std::string& python_version)
@ -33,32 +33,35 @@ namespace mamba
return fs::path();
}
#ifdef _WIN32
#ifdef _WIN32
return fs::path("Lib") / "site-packages";
#else
#else
return fs::path("lib") / concat("python", python_version) / "site-packages";
#endif
#endif
}
fs::path get_bin_directory_short_path()
{
#ifdef _WIN32
#ifdef _WIN32
return "Scripts";
#else
#else
return "bin";
#endif
#endif
}
fs::path get_python_noarch_target_path(const std::string& source_short_path, const fs::path& target_site_packages_short_path)
fs::path get_python_noarch_target_path(const std::string& source_short_path,
const fs::path& target_site_packages_short_path)
{
if (starts_with(source_short_path, "site-packages/"))
{
// replace `site_packages/` with prefix/site_packages
return target_site_packages_short_path / source_short_path.substr(14, source_short_path.size() - 14);
return target_site_packages_short_path
/ source_short_path.substr(14, source_short_path.size() - 14);
}
else if (starts_with(source_short_path, "python-scripts/"))
{
return get_bin_directory_short_path() / source_short_path.substr(15, source_short_path.size() - 15);
return get_bin_directory_short_path()
/ source_short_path.substr(15, source_short_path.size() - 15);
}
else
{

View File

@ -4,12 +4,12 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include "url.hpp"
#include <iostream>
#include <regex>
#include "thirdparty/filesystem.hpp"
#include "url.hpp"
#include "util.hpp"
namespace fs = ghc::filesystem;
@ -22,16 +22,15 @@ namespace mamba
return std::regex_search(url, re);
}
void split_anaconda_token(const std::string& url,
std::string& cleaned_url,
std::string& token)
void split_anaconda_token(const std::string& url, std::string& cleaned_url, std::string& token)
{
std::regex token_re("/t/([a-zA-Z0-9-]*)");
auto token_begin = std::sregex_iterator(url.begin(), url.end(), token_re);
if (token_begin != std::sregex_iterator())
{
token = token_begin->str().substr(3u);
cleaned_url = std::regex_replace(url, token_re, "", std::regex_constants::format_first_only);
cleaned_url
= std::regex_replace(url, token_re, "", std::regex_constants::format_first_only);
}
else
{
@ -65,7 +64,7 @@ namespace mamba
{
platform = "";
size_t pos = std::string::npos;
for(auto it = known_platforms.begin(); it != known_platforms.end(); ++it)
for (auto it = known_platforms.begin(); it != known_platforms.end(); ++it)
{
pos = url.find(*it);
if (pos != std::string::npos)
@ -128,8 +127,8 @@ namespace mamba
uc = curl_url_set(m_handle, CURLUPART_URL, url.c_str(), curl_flags);
if (uc)
{
throw std::runtime_error("Could not set URL (code: " + std::to_string(uc) +
" - url = " + url + ")");
throw std::runtime_error("Could not set URL (code: " + std::to_string(uc)
+ " - url = " + url + ")");
}
}
}
@ -310,20 +309,9 @@ namespace mamba
namespace
{
const std::vector<std::string> CURLUPART_NAMES =
{
"url",
"scheme",
"user",
"password",
"options",
"host",
"port",
"path",
"query",
"fragment",
"zoneid"
};
const std::vector<std::string> CURLUPART_NAMES
= { "url", "scheme", "user", "password", "options", "host",
"port", "path", "query", "fragment", "zoneid" };
}
std::string URLHandler::get_part(CURLUPart part)
@ -339,7 +327,6 @@ namespace mamba
else
{
return "";
//throw std::runtime_error("Could not find " + CURLUPART_NAMES[part] + " of url " + m_url);
}
}
@ -352,4 +339,4 @@ namespace mamba
throw std::runtime_error("Could not set " + s + " in url " + m_url);
}
}
}
} // namespace mamba

View File

@ -4,19 +4,20 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <iostream>
#include <iomanip>
#include <cerrno>
#include <thread>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <thread>
#ifdef _WIN32
#include <io.h>
#include <cassert>
#endif
#include "util.hpp"
#include "context.hpp"
#include "util.hpp"
namespace mamba
{
@ -35,7 +36,7 @@ namespace mamba
// False
bool lexists(const fs::path& path)
{
return fs::exists(path); // && fs::status_known(fs::symlink_status(path));
return fs::exists(path); // && fs::status_known(fs::symlink_status(path));
}
void to_human_readable_filesize(std::ostream& o, double bytes, std::size_t precision)
@ -85,18 +86,18 @@ namespace mamba
TemporaryDirectory::TemporaryDirectory()
{
bool success = false;
#ifndef _WIN32
std::string template_path = fs::temp_directory_path() / "mambadXXXXXX";
char* pth = mkdtemp((char*)template_path.c_str());
success = (pth != nullptr);
template_path = pth;
#else
std::string template_path = fs::temp_directory_path() / "mambadXXXXXX";
// include \0 terminator
auto err = _mktemp_s((char*)template_path.c_str(), template_path.size() + 1);
assert(err == 0);
success = fs::create_directory(template_path);
#endif
#ifndef _WIN32
std::string template_path = fs::temp_directory_path() / "mambadXXXXXX";
char* pth = mkdtemp(const_cast<char*>(template_path.c_str()));
success = (pth != nullptr);
template_path = pth;
#else
std::string template_path = fs::temp_directory_path() / "mambadXXXXXX";
// include \0 terminator
auto err = _mktemp_s(const_cast<char*>(template_path.c_str()), template_path.size() + 1);
assert(err == 0);
success = fs::create_directory(template_path);
#endif
if (!success)
{
throw std::runtime_error("Could not create temporary directory!");
@ -185,7 +186,8 @@ namespace mamba
bool ends_with(const std::string_view& str, const std::string_view& suffix)
{
return str.size() >= suffix.size() && 0 == str.compare(str.size() - suffix.size(), suffix.size(), suffix);
return str.size() >= suffix.size()
&& 0 == str.compare(str.size() - suffix.size(), suffix.size(), suffix);
}
bool starts_with(const std::string_view& str, const std::string_view& prefix)
@ -227,7 +229,6 @@ namespace mamba
return end == std::string::npos ? "" : input.substr(0, end + 1);
}
std::vector<std::string> split(const std::string_view& input,
const std::string_view& sep,
std::size_t max_split)
@ -239,7 +240,8 @@ namespace mamba
{
if (input[i] == sep[0] && input.substr(i, n) == sep)
{
if (max_split-- <= 0) break;
if (max_split-- <= 0)
break;
result.emplace_back(input.substr(j, i - j));
i = j = i + n;
}
@ -256,19 +258,23 @@ namespace mamba
const std::string_view& sep,
std::size_t max_split)
{
if (max_split == SIZE_MAX) return split(input, sep, max_split);
if (max_split == SIZE_MAX)
return split(input, sep, max_split);
std::vector<std::string> result;
std::ptrdiff_t i, j, len = static_cast<std::ptrdiff_t>(input.size()),
n = static_cast<std::ptrdiff_t>(sep.size());
n = static_cast<std::ptrdiff_t>(sep.size());
i = j = len;
while (i >= n)
{
if (input[i - 1] == sep[n - 1] && input.substr(i - n, n) == sep)
{
if (max_split-- <= 0) { break; }
if (max_split-- <= 0)
{
break;
}
result.emplace_back(input.substr(i, j - i));
i = j = i - n;
}
@ -307,9 +313,8 @@ namespace mamba
std::string string_transform(const std::string_view& input, int (*functor)(int))
{
std::string res(input);
std::transform(res.begin(), res.end(), res.begin(),
[&](unsigned char c) { return functor(c); }
);
std::transform(
res.begin(), res.end(), res.begin(), [&](unsigned char c) { return functor(c); });
return res;
}
@ -334,11 +339,12 @@ namespace mamba
in.seekg(0, std::ios::beg);
in.read(&contents[0], contents.size());
in.close();
return(contents);
return (contents);
}
else
{
throw std::system_error(errno, std::system_category(), "failed to open " + file_path.string());
throw std::system_error(
errno, std::system_category(), "failed to open " + file_path.string());
}
}
@ -347,7 +353,8 @@ namespace mamba
std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary);
if (file_stream.fail())
{
throw std::system_error(errno, std::system_category(), "failed to open " + file_path.string());
throw std::system_error(
errno, std::system_category(), "failed to open " + file_path.string());
}
std::vector<std::string> output;
@ -355,7 +362,8 @@ namespace mamba
while (std::getline(file_stream, line))
{
// Remove the trailing \r to accomodate Windows line endings.
if ((!line.empty()) && (line.back() == '\r')) line.pop_back();
if ((!line.empty()) && (line.back() == '\r'))
line.pop_back();
output.push_back(line);
}
@ -364,4 +372,4 @@ namespace mamba
return output;
}
}
} // namespace mamba

View File

@ -4,13 +4,14 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <iostream>
#include "openssl/sha.h"
#include "openssl/md5.h"
#include "validate.hpp"
#include <iostream>
#include "openssl/md5.h"
#include "openssl/sha.h"
#include "output.hpp"
#include "util.hpp"
#include "validate.hpp"
namespace validate
{
@ -80,4 +81,4 @@ namespace validate
{
return fs::file_size(path) == validation;
}
}
} // namespace validate

View File

@ -1,4 +1,5 @@
#include <gtest/gtest.h>
#include <fstream>
#include <string>
@ -52,4 +53,4 @@ namespace mamba
src_end.close();
dst_end.close();
}
}
} // namespace mamba

View File

@ -7,7 +7,8 @@ namespace mamba
TEST(activation, activation)
{
PosixActivator a;
// std::cout << a.add_prefix_to_path("/home/wolfv/miniconda3", 0) << std::endl;
// std::cout << a.activate("/home/wolfv/miniconda3/", false) << std::endl;
// std::cout << a.add_prefix_to_path("/home/wolfv/miniconda3", 0) <<
// std::endl; std::cout << a.activate("/home/wolfv/miniconda3/", false) <<
// std::endl;
}
}
} // namespace mamba

View File

@ -1,21 +1,20 @@
#include <gtest/gtest.h>
#include "channel.hpp"
#include "thirdparty/filesystem.hpp"
#include "url.hpp"
#include "util.hpp"
#include "thirdparty/filesystem.hpp"
namespace fs = ghc::filesystem;
namespace mamba
{
#ifdef __linux__
#ifdef __linux__
std::string platform("linux-64");
#elif __APPLE__
#elif __APPLE__
std::string platform("osx-64");
#elif _WIN32
#elif _WIN32
std::string platform("win-64");
#endif
#endif
TEST(ChannelContext, init)
{
@ -75,23 +74,23 @@ namespace mamba
std::string value4 = "/home/mamba/test/channel_b";
Channel& c4 = make_channel(value4);
EXPECT_EQ(c4.scheme(), "file");
#ifdef _WIN32
#ifdef _WIN32
std::string driveletter = fs::absolute(fs::path("/")).string().substr(0, 1);
EXPECT_EQ(c4.location(), driveletter + ":/home/mamba/test");
#else
#else
EXPECT_EQ(c4.location(), "/home/mamba/test");
#endif
#endif
EXPECT_EQ(c4.name(), "channel_b");
EXPECT_EQ(c4.platform(), "");
std::string value5 = "/home/mamba/test/channel_b/" + platform;
Channel& c5 = make_channel(value5);
EXPECT_EQ(c5.scheme(), "file");
#ifdef _WIN32
#ifdef _WIN32
EXPECT_EQ(c5.location(), driveletter + ":/home/mamba/test");
#else
#else
EXPECT_EQ(c5.location(), "/home/mamba/test");
#endif
#endif
EXPECT_EQ(c5.name(), "channel_b");
EXPECT_EQ(c5.platform(), platform);
}
@ -123,7 +122,7 @@ namespace mamba
EXPECT_EQ(res.size(), on_win ? 8u : 6u);
EXPECT_EQ(res[0], "https://conda.anaconda.org/conda-forge/" + platform);
EXPECT_EQ(res[1], "https://conda.anaconda.org/conda-forge/noarch");
EXPECT_EQ(res[2], "https://repo.anaconda.com/pkgs/main/" + platform);
EXPECT_EQ(res[2], "https://repo.anaconda.com/pkgs/main/" + platform);
EXPECT_EQ(res[3], "https://repo.anaconda.com/pkgs/main/noarch");
EXPECT_EQ(res[4], "https://repo.anaconda.com/pkgs/r/" + platform);
EXPECT_EQ(res[5], "https://repo.anaconda.com/pkgs/r/noarch");
@ -137,12 +136,12 @@ namespace mamba
EXPECT_EQ(res2[4], res[4]);
EXPECT_EQ(res2[5], res[5]);
#ifdef _WIN32
#ifdef _WIN32
EXPECT_EQ(res[6], "https://repo.anaconda.com/pkgs/msys2/" + platform);
EXPECT_EQ(res[7], "https://repo.anaconda.com/pkgs/msys2/noarch");
EXPECT_EQ(res2[6], res[6]);
EXPECT_EQ(res2[7], res[7]);
#endif
#endif
std::vector<std::string> local_urls = { "./channel_b", "./channel_a" };
std::vector<std::string> local_res = calculate_channel_urls(local_urls, false);
@ -153,4 +152,4 @@ namespace mamba
EXPECT_EQ(local_res[2], current_dir + "channel_a/" + platform);
EXPECT_EQ(local_res[3], current_dir + "channel_a/noarch");
}
}
} // namespace mamba

View File

@ -1,10 +1,10 @@
#include <gtest/gtest.h>
#include "match_spec.hpp"
#include "context.hpp"
#include "link.hpp"
#include "history.hpp"
#include "fsutil.hpp"
#include "history.hpp"
#include "link.hpp"
#include "match_spec.hpp"
namespace mamba
{
@ -128,9 +128,11 @@ namespace mamba
EXPECT_EQ(ms.build_number, "<=3");
}
{
MatchSpec ms("xtensor[url=file:///home/wolfv/Downloads/xtensor-0.21.4-hc9558a2_0.tar.bz2]");
MatchSpec ms("xtensor[url=file:///home/wolfv/Downloads/"
"xtensor-0.21.4-hc9558a2_0.tar.bz2]");
EXPECT_EQ(ms.name, "xtensor");
EXPECT_EQ(ms.brackets["url"], "file:///home/wolfv/Downloads/xtensor-0.21.4-hc9558a2_0.tar.bz2");
EXPECT_EQ(ms.brackets["url"],
"file:///home/wolfv/Downloads/xtensor-0.21.4-hc9558a2_0.tar.bz2");
EXPECT_EQ(ms.fn, "file:///home/wolfv/Downloads/xtensor-0.21.4-hc9558a2_0.tar.bz2");
}
{
@ -204,7 +206,7 @@ namespace mamba
if (on_linux)
{
auto home = env::expand_user("~");
EXPECT_EQ(path::starts_with_home(home / "test" / "file.txt" ), true);
EXPECT_EQ(path::starts_with_home(home / "test" / "file.txt"), true);
EXPECT_EQ(path::starts_with_home("~"), true);
EXPECT_EQ(path::starts_with_home("/opt/bin"), false);
}
@ -243,4 +245,4 @@ namespace mamba
EXPECT_THROW(path::is_writable("/tmp/this/path/doesnt/exist"), std::runtime_error);
}
}
}
} // namespace mamba

View File

@ -10,7 +10,8 @@ namespace mamba
auto prefixes = e.list_all_known_prefixes();
e.register_env(env::expand_user("~/some/env"));
auto new_prefixes = e.list_all_known_prefixes();
// the prefix should be cleaned out, because it doesn't have the `conda-meta/history` file
// the prefix should be cleaned out, because it doesn't have the
// `conda-meta/history` file
EXPECT_EQ(new_prefixes.size(), prefixes.size());
}
}
} // namespace mamba

View File

@ -48,17 +48,16 @@ namespace mamba
class test_visitor : private default_visitor<G>
{
public:
using base_type = default_visitor<G>;
using node_id = typename base_type::node_id;
using predecessor_map = std::map<node_id, node_id>;
using edge_map = std::map<node_id, node_id>;
using base_type::start_node;
using base_type::finish_edge;
using base_type::finish_node;
using base_type::start_edge;
using base_type::start_node;
using base_type::tree_edge;
using base_type::finish_edge;
void back_edge(node_id from, node_id to, const G&)
{
@ -81,7 +80,6 @@ namespace mamba
}
private:
edge_map m_back_edges;
edge_map m_cross_edges;
};
@ -91,11 +89,11 @@ namespace mamba
using node_list = graph<int>::node_list;
using edge_list = graph<int>::edge_list;
auto g = build_graph();
EXPECT_EQ(g.get_node_list(), node_list({0u, 1u, 2u, 3u, 4u, 5u, 6u}));
EXPECT_EQ(g.get_edge_list(0u), edge_list({1u, 2u}));
EXPECT_EQ(g.get_edge_list(1u), edge_list({3u, 4u}));
EXPECT_EQ(g.get_edge_list(2u), edge_list({3u, 5u}));
EXPECT_EQ(g.get_edge_list(3u), edge_list({6u}));
EXPECT_EQ(g.get_node_list(), node_list({ 0u, 1u, 2u, 3u, 4u, 5u, 6u }));
EXPECT_EQ(g.get_edge_list(0u), edge_list({ 1u, 2u }));
EXPECT_EQ(g.get_edge_list(1u), edge_list({ 3u, 4u }));
EXPECT_EQ(g.get_edge_list(2u), edge_list({ 3u, 5u }));
EXPECT_EQ(g.get_edge_list(3u), edge_list({ 6u }));
}
TEST(graph, depth_first_search)
@ -124,4 +122,4 @@ namespace mamba
EXPECT_TRUE(vis.get_back_edge_map().empty());
EXPECT_TRUE(vis.get_cross_edge_map().empty());
}
}
} // namespace mamba

View File

@ -1,7 +1,7 @@
#include <gtest/gtest.h>
#include "util.hpp"
#include "shell_init.hpp"
#include "util.hpp"
namespace mamba
{
@ -12,7 +12,8 @@ namespace mamba
TEST(shell_init, bashrc_modifications)
{
// modify_rc_file("/home/wolfv/Programs/mamba/test/.bashrc", "/home/wolfv/superconda/", "bash");
// modify_rc_file("/home/wolfv/Programs/mamba/test/.bashrc",
// "/home/wolfv/superconda/", "bash");
}
TEST(shell_init, expand_user)
@ -23,4 +24,4 @@ namespace mamba
EXPECT_TRUE(starts_with(expanded.string(), "/home/"));
}
}
}
} // namespace mamba

View File

@ -16,32 +16,32 @@ namespace mamba
TEST(util, split)
{
std::string a = "hello.again.it's.me.mario";
std::vector<std::string> e1 = {"hello", "again", "it's", "me", "mario"};
std::vector<std::string> e1 = { "hello", "again", "it's", "me", "mario" };
EXPECT_EQ(split(a, "."), e1);
std::vector<std::string> s2 = {"hello", "again", "it's.me.mario"};
std::vector<std::string> s2 = { "hello", "again", "it's.me.mario" };
EXPECT_EQ(split(a, ".", 2), s2);
EXPECT_EQ(rsplit(a, "."), e1);
std::vector<std::string> r2 = {"hello.again.it's", "me", "mario"};
std::vector<std::string> r2 = { "hello.again.it's", "me", "mario" };
EXPECT_EQ(rsplit(a, ".", 2), r2);
std::string b = "...";
auto es1 = std::vector<std::string>{"", "", "", ""};
auto es2 = std::vector<std::string>{"", ".."};
auto es1 = std::vector<std::string>{ "", "", "", "" };
auto es2 = std::vector<std::string>{ "", ".." };
EXPECT_EQ(split(b, "."), es1);
EXPECT_EQ(split(b, ".", 1), es2);
std::vector<std::string> v = {"xtensor==0.12.3"};
std::vector<std::string> v = { "xtensor==0.12.3" };
EXPECT_EQ(split(v[0], ":"), v);
EXPECT_EQ(rsplit(v[0], ":"), v);
EXPECT_EQ(split(v[0], ":", 2), v);
EXPECT_EQ(rsplit(v[0], ":", 2), v);
std::vector<std::string> v2 = {"conda-forge/linux64", "", "xtensor==0.12.3"};
std::vector<std::string> v2 = { "conda-forge/linux64", "", "xtensor==0.12.3" };
EXPECT_EQ(split("conda-forge/linux64::xtensor==0.12.3", ":", 2), v2);
EXPECT_EQ(rsplit("conda-forge/linux64::xtensor==0.12.3", ":", 2), v2);
std::vector<std::string> v21 = {"conda-forge/linux64:", "xtensor==0.12.3"};
std::vector<std::string> v21 = { "conda-forge/linux64:", "xtensor==0.12.3" };
EXPECT_EQ(rsplit("conda-forge/linux64::xtensor==0.12.3", ":", 1), v21);
}
@ -62,7 +62,8 @@ namespace mamba
EXPECT_TRUE(starts_with(prefix, "/Yes/Thats/great/\n"));
std::string prefix_unicode = "/I/am/Dörte朩æ©fðgb®/PREFIX\n\nabcdefg\nxyz";
replace_all(prefix_unicode, "/I/am/Dörte朩æ©fðgb®/PREFIX", "/home/åéäáßðæœ©ðfßfáðß/123123123");
replace_all(
prefix_unicode, "/I/am/Dörte朩æ©fðgb®/PREFIX", "/home/åéäáßðæœ©ðfßfáðß/123123123");
EXPECT_EQ(prefix_unicode, "/home/åéäáßðæœ©ðfßfáðß/123123123\n\nabcdefg\nxyz");
}
}
} // namespace mamba

View File

@ -8,7 +8,7 @@ namespace mamba
{
TEST(thread_utils, interrupt)
{
#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
int res = 0;
// Ensures the compiler doe snot optimize away Context::instance()
std::string current_command = Context::instance().current_command;
@ -16,27 +16,25 @@ namespace mamba
Console::instance().init_multi_progress();
{
interruption_guard g([&res]()
{
// Test for double free (segfault if that happends)
Console::instance().init_multi_progress();
res = -1;
});
for (size_t i = 0; i < 5; ++i)
{
thread t([&res]()
{
++res;
std::this_thread::sleep_for(std::chrono::milliseconds(300));
interruption_guard g([&res]() {
// Test for double free (segfault if that happends)
Console::instance().init_multi_progress();
res = -1;
});
t.detach();
}
pthread_kill(get_cleaning_thread_id(), SIGINT);
std::this_thread::sleep_for(std::chrono::seconds(1));
for (size_t i = 0; i < 5; ++i)
{
thread t([&res]() {
++res;
std::this_thread::sleep_for(std::chrono::milliseconds(300));
});
t.detach();
}
pthread_kill(get_cleaning_thread_id(), SIGINT);
std::this_thread::sleep_for(std::chrono::seconds(1));
}
EXPECT_EQ(res, -1);
#endif
}
}
} // namespace mamba

View File

@ -1,19 +1,18 @@
#include <gtest/gtest.h>
#include "util.hpp"
#include "subdirdata.hpp"
#include "util.hpp"
namespace mamba
{
TEST(transfer, file_not_exist)
{
#ifdef __linux__
#ifdef __linux__
Context::instance().quiet = true;
{
mamba::MultiDownloadTarget multi_dl;
mamba::MSubdirData cf("conda-forge/linux-64",
"file:///nonexistent/repodata.json",
"/tmp/zyx.json");
mamba::MSubdirData cf(
"conda-forge/linux-64", "file:///nonexistent/repodata.json", "/tmp/zyx.json");
cf.load();
multi_dl.add(cf.target());
@ -27,14 +26,13 @@ namespace mamba
}
{
mamba::MultiDownloadTarget multi_dl;
mamba::MSubdirData cf("conda-forge/noarch",
"file:///nonexistent/repodata.json",
"/tmp/zyx.json");
mamba::MSubdirData cf(
"conda-forge/noarch", "file:///nonexistent/repodata.json", "/tmp/zyx.json");
cf.load();
multi_dl.add(cf.target());
EXPECT_THROW(multi_dl.download(true), std::runtime_error);
}
Context::instance().quiet = false;
#endif
#endif
}
}
} // namespace mamba

View File

@ -1,8 +1,7 @@
#include <gtest/gtest.h>
#include "url.hpp"
#include "thirdparty/filesystem.hpp"
#include "url.hpp"
namespace fs = ghc::filesystem;
namespace mamba
@ -31,29 +30,29 @@ namespace mamba
EXPECT_EQ(m.query(), "query=123&xyz=3333");
}
{
#ifdef _WIN32
#ifdef _WIN32
URLHandler m("file://C:/Users/wolfv/test/document.json");
EXPECT_EQ(m.scheme(), "file");
EXPECT_EQ(m.path(), "C:/Users/wolfv/test/document.json");
#else
#else
URLHandler m("file:///home/wolfv/test/document.json");
EXPECT_EQ(m.scheme(), "file");
EXPECT_EQ(m.path(), "/home/wolfv/test/document.json");
#endif
#endif
}
}
TEST(url, path_to_url)
{
auto url = path_to_url("/users/test/miniconda3");
#ifndef _WIN32
EXPECT_EQ(url, "file:///users/test/miniconda3");
#else
std::string driveletter = fs::absolute(fs::path("/")).string().substr(0, 1);
EXPECT_EQ(url, std::string("file://") + driveletter + ":/users/test/miniconda3");
auto url2 = path_to_url("D:\\users\\test\\miniconda3");
EXPECT_EQ(url2, "file://D:/users/test/miniconda3");
#endif
#ifndef _WIN32
EXPECT_EQ(url, "file:///users/test/miniconda3");
#else
std::string driveletter = fs::absolute(fs::path("/")).string().substr(0, 1);
EXPECT_EQ(url, std::string("file://") + driveletter + ":/users/test/miniconda3");
auto url2 = path_to_url("D:\\users\\test\\miniconda3");
EXPECT_EQ(url2, "file://D:/users/test/miniconda3");
#endif
}
TEST(url, has_scheme)
@ -113,7 +112,6 @@ namespace mamba
TEST(url, split_ananconda_token)
{
std::string input, cleaned_url, token;
{
input = "https://1.2.3.4/t/tk-123-456/path";
@ -168,25 +166,27 @@ namespace mamba
EXPECT_EQ(auth, "u:p");
EXPECT_EQ(token, "x1029384756");
#ifdef _WIN32
split_scheme_auth_token("file://C:/Users/wolfv/test.json", remaining_url, scheme, auth, token);
#ifdef _WIN32
split_scheme_auth_token(
"file://C:/Users/wolfv/test.json", remaining_url, scheme, auth, token);
EXPECT_EQ(remaining_url, "C:/Users/wolfv/test.json");
EXPECT_EQ(scheme, "file");
EXPECT_EQ(auth, "");
EXPECT_EQ(token, "");
#else
#else
split_scheme_auth_token("file:///home/wolfv/test.json", remaining_url, scheme, auth, token);
EXPECT_EQ(remaining_url, "/home/wolfv/test.json");
EXPECT_EQ(scheme, "file");
EXPECT_EQ(auth, "");
EXPECT_EQ(token, "");
#endif
#endif
}
TEST(url, split_platform)
{
std::string input = "https://1.2.3.4/t/tk-123/linux-64/path";
std::vector<std::string> known_platforms = {"noarch", "linux-32", "linux-64", "linux-aarch64"};
std::vector<std::string> known_platforms
= { "noarch", "linux-32", "linux-64", "linux-aarch64" };
std::string cleaned_url, platform;
split_platform(known_platforms, input, cleaned_url, platform);
EXPECT_EQ(cleaned_url, "https://1.2.3.4/t/tk-123/path");
@ -201,4 +201,4 @@ namespace mamba
EXPECT_TRUE(is_path("/"));
EXPECT_FALSE(is_path("file://makefile"));
}
}
} // namespace mamba