mirror of https://github.com/mamba-org/mamba.git
Use xdg schemas for config saving/reading (minified) (#2714)
Co-authored-by: Danny Farrell <dan@cyrusbio.com>
This commit is contained in:
parent
2b0c975429
commit
00fb86c726
|
@ -54,6 +54,9 @@ namespace mamba
|
|||
std::map<std::string, std::string> copy();
|
||||
std::string platform();
|
||||
fs::u8path home_directory();
|
||||
fs::u8path user_config_dir();
|
||||
fs::u8path user_data_dir();
|
||||
fs::u8path user_cache_dir();
|
||||
|
||||
fs::u8path expand_user(const fs::u8path& path);
|
||||
fs::u8path shrink_user(const fs::u8path& path);
|
||||
|
|
|
@ -5,4 +5,11 @@ namespace mamba
|
|||
{
|
||||
void remove_menu_from_json(const fs::u8path& json_file, TransactionContext* context);
|
||||
void create_menu_from_json(const fs::u8path& json_file, TransactionContext* context);
|
||||
#ifdef _WIN32
|
||||
namespace win
|
||||
{
|
||||
fs::u8path get_folder(const std::string& id);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1751,6 +1751,16 @@ namespace mamba
|
|||
return res;
|
||||
}
|
||||
|
||||
// Precedence is initially set least to most, and then at the end the list is reversed.
|
||||
// Configuration::set_rc_values iterates over all config options, and then over all config
|
||||
// file source. Essentially first come first serve.
|
||||
// just FYI re "../conda": env::user_config_dir's default value is $XDG_CONFIG_HOME/mamba
|
||||
// But we wanted to also allow $XDG_CONFIG_HOME/conda and '..' seems like the best way to
|
||||
// make it conda/mamba compatible. Otherwise I would have to set user_config_dir to either
|
||||
// be just $XDG_CONFIG_HOME and always supply mamba after calling it, or I would have to
|
||||
// give env::user_config_dir a mamba argument, all so I can supply conda in a few default
|
||||
// cases. It seems like ../conda is an easier solution
|
||||
//
|
||||
std::vector<fs::u8path> Configuration::compute_default_rc_sources(const RCConfigLevel& level)
|
||||
{
|
||||
auto& ctx = Context::instance();
|
||||
|
@ -1776,11 +1786,30 @@ namespace mamba
|
|||
ctx.prefix_params.root_prefix / "condarc.d",
|
||||
ctx.prefix_params.root_prefix / ".mambarc" };
|
||||
|
||||
std::vector<fs::u8path> home = { env::home_directory() / ".conda/.condarc",
|
||||
env::home_directory() / ".conda/condarc",
|
||||
env::home_directory() / ".conda/condarc.d",
|
||||
env::home_directory() / ".condarc",
|
||||
env::home_directory() / ".mambarc" };
|
||||
std::vector<fs::u8path> conda_user = {
|
||||
env::user_config_dir() / "../conda/.condarc",
|
||||
env::user_config_dir() / "../conda/condarc",
|
||||
env::user_config_dir() / "../conda/condarc.d",
|
||||
env::home_directory() / ".conda/.condarc",
|
||||
env::home_directory() / ".conda/condarc",
|
||||
env::home_directory() / ".conda/condarc.d",
|
||||
env::home_directory() / ".condarc",
|
||||
};
|
||||
if (env::get("CONDARC"))
|
||||
{
|
||||
conda_user.push_back(fs::u8path(env::get("CONDARC").value()));
|
||||
}
|
||||
|
||||
std::vector<fs::u8path> mamba_user = {
|
||||
env::user_config_dir() / ".mambarc", env::user_config_dir() / "mambarc",
|
||||
env::user_config_dir() / "mambarc.d", env::home_directory() / ".mamba/.mambarc",
|
||||
env::home_directory() / ".mamba/mambarc", env::home_directory() / ".mamba/mambarc.d",
|
||||
env::home_directory() / ".mambarc",
|
||||
};
|
||||
if (env::get("MAMBARC"))
|
||||
{
|
||||
mamba_user.push_back(fs::u8path(env::get("MAMBARC").value()));
|
||||
}
|
||||
|
||||
std::vector<fs::u8path> prefix = { ctx.prefix_params.target_prefix / ".condarc",
|
||||
ctx.prefix_params.target_prefix / "condarc",
|
||||
|
@ -1799,7 +1828,8 @@ namespace mamba
|
|||
}
|
||||
if (level >= RCConfigLevel::kHomeDir)
|
||||
{
|
||||
sources.insert(sources.end(), home.begin(), home.end());
|
||||
sources.insert(sources.end(), conda_user.begin(), conda_user.end());
|
||||
sources.insert(sources.end(), mamba_user.begin(), mamba_user.end());
|
||||
}
|
||||
if ((level >= RCConfigLevel::kTargetPrefix) && !ctx.prefix_params.target_prefix.empty())
|
||||
{
|
||||
|
|
|
@ -5,11 +5,13 @@
|
|||
// The full license is in the file LICENSE, distributed with this software.
|
||||
|
||||
#include "mamba/core/environment.hpp"
|
||||
#include "mamba/core/util.hpp"
|
||||
#include "mamba/core/util_string.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <mutex>
|
||||
|
||||
#include "mamba/core/menuinst.hpp"
|
||||
#include "mamba/core/output.hpp"
|
||||
#include "mamba/core/util_os.hpp"
|
||||
#endif
|
||||
|
@ -267,7 +269,49 @@ namespace mamba
|
|||
throw std::runtime_error("HOME not set.");
|
||||
}
|
||||
#endif
|
||||
return maybe_home;
|
||||
return fs::u8path(maybe_home);
|
||||
}
|
||||
|
||||
fs::u8path user_config_dir()
|
||||
{
|
||||
std::string maybe_user_config_dir = env::get("XDG_CONFIG_HOME").value_or("");
|
||||
if (maybe_user_config_dir.empty())
|
||||
{
|
||||
#ifdef _WIN32
|
||||
maybe_user_config_dir = ::mamba::win::get_folder("roamingappdata");
|
||||
#else
|
||||
maybe_user_config_dir = home_directory() / ".config";
|
||||
#endif
|
||||
}
|
||||
return fs::u8path(maybe_user_config_dir) / "mamba";
|
||||
}
|
||||
|
||||
fs::u8path user_data_dir()
|
||||
{
|
||||
std::string maybe_user_data_dir = env::get("XDG_DATA_HOME").value_or("");
|
||||
if (maybe_user_data_dir.empty())
|
||||
{
|
||||
#ifdef _WIN32
|
||||
maybe_user_data_dir = ::mamba::win::get_folder("roamingappdata");
|
||||
#else
|
||||
maybe_user_data_dir = home_directory() / ".local" / "share";
|
||||
#endif
|
||||
}
|
||||
return fs::u8path(maybe_user_data_dir) / "mamba";
|
||||
}
|
||||
|
||||
fs::u8path user_cache_dir()
|
||||
{
|
||||
std::string maybe_user_cache_dir = env::get("XDG_CACHE_HOME").value_or("");
|
||||
if (maybe_user_cache_dir.empty())
|
||||
{
|
||||
#ifdef _WIN32
|
||||
maybe_user_cache_dir = ::mamba::win::get_folder("localappdata");
|
||||
#else
|
||||
maybe_user_cache_dir = home_directory() / ".cache";
|
||||
#endif
|
||||
}
|
||||
return fs::u8path(maybe_user_cache_dir) / "mamba";
|
||||
}
|
||||
|
||||
fs::u8path expand_user(const fs::u8path& path)
|
||||
|
|
|
@ -168,9 +168,9 @@ namespace mamba
|
|||
}
|
||||
|
||||
const std::map<std::string, KNOWNFOLDERID> knownfolders = {
|
||||
{ "programs", FOLDERID_Programs },
|
||||
{ "profile", FOLDERID_Profile },
|
||||
{ "documents", FOLDERID_Documents },
|
||||
{ "programs", FOLDERID_Programs }, { "profile", FOLDERID_Profile },
|
||||
{ "documents", FOLDERID_Documents }, { "roamingappdata", FOLDERID_RoamingAppData },
|
||||
{ "programdata", FOLDERID_ProgramData }, { "localappdata", FOLDERID_LocalAppData },
|
||||
};
|
||||
|
||||
fs::u8path get_folder(const std::string& id)
|
||||
|
|
|
@ -114,7 +114,7 @@ namespace mamba
|
|||
|
||||
const fs::u8path& proc_dir()
|
||||
{
|
||||
static const auto path = env::home_directory() / ".mamba" / "proc";
|
||||
static auto path = env::user_cache_dir() / "proc";
|
||||
return path;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,10 @@ def tmp_home(
|
|||
for env in used_homes:
|
||||
os.environ[env] = str(new_home)
|
||||
|
||||
if platform.system() == "Windows":
|
||||
os.environ["APPDATA"] = str(new_home / "AppData" / "Roaming")
|
||||
os.environ["LOCALAPPDATA"] = str(new_home / "AppData" / "Local")
|
||||
|
||||
yield new_home
|
||||
|
||||
# Pytest would clean it automatically but this can be large (0.5 Gb for repodata)
|
||||
|
@ -83,7 +87,7 @@ def tmp_home(
|
|||
def tmp_clean_env(tmp_environ: None) -> None:
|
||||
"""Remove all Conda/Mamba activation artifacts from environment."""
|
||||
for k, v in os.environ.items():
|
||||
if k.startswith(("CONDA", "_CONDA", "MAMBA", "_MAMBA")):
|
||||
if k.startswith(("CONDA", "_CONDA", "MAMBA", "_MAMBA", "XDG_")):
|
||||
del os.environ[k]
|
||||
|
||||
def keep_in_path(
|
||||
|
@ -179,3 +183,48 @@ def tmp_xtensor_env(tmp_prefix: pathlib.Path) -> Generator[pathlib.Path, None, N
|
|||
"""An activated environment with Xtensor installed."""
|
||||
helpers.install("-c", "conda-forge", "--json", "xtensor", no_dry_run=True)
|
||||
yield tmp_prefix
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user_config_dir(tmp_home: pathlib.Path) -> Generator[pathlib.Path, None, None]:
|
||||
"""Location of config files that are generated from mamba"""
|
||||
maybe_xdg_config = os.getenv("XDG_CONFIG_DIR", "")
|
||||
if maybe_xdg_config:
|
||||
yield pathlib.Path(maybe_xdg_config)
|
||||
system = platform.system()
|
||||
if system == "Linux" or system == "Darwin":
|
||||
yield tmp_home / ".config/mamba"
|
||||
elif system == "Windows":
|
||||
yield pathlib.Path(os.environ["APPDATA"]) / "mamba"
|
||||
else:
|
||||
raise RuntimeError(f"Unsupported system {system}")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user_data_dir(tmp_home: pathlib.Path) -> Generator[pathlib.Path, None, None]:
|
||||
"""Location of data files that are generated from mamba"""
|
||||
maybe_xdg_data = os.getenv("XDG_DATA_DIR", "")
|
||||
if maybe_xdg_data:
|
||||
yield pathlib.Path(maybe_xdg_data)
|
||||
system = platform.system()
|
||||
if system == "Linux" or system == "Darwin":
|
||||
yield tmp_home / ".local/share/mamba"
|
||||
elif system == "Windows":
|
||||
yield pathlib.Path(os.environ["APPDATA"]) / "mamba"
|
||||
else:
|
||||
raise RuntimeError(f"Unsupported system {system}")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user_cache_dir(tmp_home: pathlib.Path) -> Generator[pathlib.Path, None, None]:
|
||||
"""Location of data files that are generated from mamba"""
|
||||
maybe_xdg_cache = os.getenv("XDG_CACHE_DIR", "")
|
||||
if maybe_xdg_cache:
|
||||
yield pathlib.Path(maybe_xdg_cache)
|
||||
system = platform.system()
|
||||
if system == "Linux" or system == "Darwin":
|
||||
yield tmp_home / ".cache/mamba"
|
||||
elif system == "Windows":
|
||||
yield pathlib.Path(os.environ["LOCALAPPDATA"]) / "mamba"
|
||||
else:
|
||||
raise RuntimeError(f"Unsupported system {system}")
|
||||
|
|
|
@ -45,7 +45,15 @@ def rc_file_text(rc_file_args):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def rc_file(request, rc_file_text, tmp_home, tmp_root_prefix, tmp_prefix, tmp_path):
|
||||
def rc_file(
|
||||
request,
|
||||
rc_file_text,
|
||||
tmp_home,
|
||||
tmp_root_prefix,
|
||||
tmp_prefix,
|
||||
tmp_path,
|
||||
user_config_dir,
|
||||
):
|
||||
"""Parametrizable fixture to create an rc file at the desired location.
|
||||
|
||||
The file is created in an isolated folder and set as the prefix, root prefix, or
|
||||
|
@ -59,6 +67,11 @@ def rc_file(request, rc_file_text, tmp_home, tmp_root_prefix, tmp_prefix, tmp_pa
|
|||
rc_file = tmp_root_prefix / rc_filename
|
||||
elif where == "prefix":
|
||||
rc_file = tmp_prefix / rc_filename
|
||||
elif where == "user_config_dir":
|
||||
rc_file = user_config_dir / rc_filename
|
||||
elif where == "env_set_xdg":
|
||||
os.environ["XDG_CONFIG_HOME"] = str(tmp_home / "custom_xdg_config_dir")
|
||||
rc_file = tmp_home / "custom_xdg_config_dir" / "mamba" / rc_filename
|
||||
elif where == "absolute":
|
||||
rc_file = Path(rc_filename)
|
||||
else:
|
||||
|
@ -114,7 +127,6 @@ class TestConfigSources:
|
|||
res = config("sources", quiet_flag)
|
||||
assert res.startswith("Configuration files (by precedence order):")
|
||||
|
||||
# TODO: test OS specific sources
|
||||
# TODO: test system located sources?
|
||||
@pytest.mark.parametrize(
|
||||
"rc_file",
|
||||
|
@ -127,6 +139,8 @@ class TestConfigSources:
|
|||
# "/var/lib/conda/condarc",
|
||||
# "/var/lib/conda/condarc.d/",
|
||||
# "/var/lib/conda/.mambarc",
|
||||
("user_config_dir", "mambarc"),
|
||||
("env_set_xdg", "mambarc"),
|
||||
("home", ".conda/.condarc"),
|
||||
("home", ".conda/condarc"),
|
||||
("home", ".conda/condarc.d"),
|
||||
|
|
Loading…
Reference in New Issue