use libmamba LockFile instead of conda's one

add CLI parser for clean -l,--locks
rely on libmamba for that specific clean action
This commit is contained in:
Adrien DELSALLE 2021-10-25 14:13:55 +02:00
parent bff16c2bdc
commit a416754bcb
No known key found for this signature in database
GPG Key ID: 639D9226C33B92BB
3 changed files with 82 additions and 14 deletions

View File

@ -10,6 +10,9 @@
#include "nlohmann/json.hpp"
#include "mamba/api/clean.hpp"
#include "mamba/api/configuration.hpp"
#include "mamba/core/channel.hpp"
#include "mamba/core/context.hpp"
#include "mamba/core/package_handling.hpp"
@ -52,6 +55,8 @@ PYBIND11_MODULE(bindings, m)
});
py::implicitly_convertible<std::string, fs::path>();
py::class_<mamba::LockFile>(m, "LockFile").def(py::init<fs::path>());
py::register_exception<mamba_error>(m, "MambaNativeException");
py::add_ostream_redirect(m, "ostream_redirect");
@ -377,6 +382,19 @@ PYBIND11_MODULE(bindings, m)
return s;
});
m.def("clean", &clean);
py::class_<Configuration, std::unique_ptr<Configuration, py::nodelete>>(m, "Configuration")
.def(py::init([]() {
return std::unique_ptr<Configuration, py::nodelete>(&Configuration::instance());
}))
.def_property(
"show_banner",
[]() -> bool { return Configuration::instance().at("show_banner").value<bool>(); },
[](py::object&, bool val) {
Configuration::instance().at("show_banner").set_value(val);
});
m.def("get_channels", &get_channels);
m.def("transmute", &transmute);
@ -451,7 +469,15 @@ PYBIND11_MODULE(bindings, m)
m.attr("SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED") = SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED;
m.attr("SOLVER_FLAG_STRICT_REPO_PRIORITY") = SOLVER_FLAG_STRICT_REPO_PRIORITY;
// INSTALL FLAGS
m.attr("MAMBA_NO_DEPS") = MAMBA_NO_DEPS;
m.attr("MAMBA_ONLY_DEPS") = MAMBA_ONLY_DEPS;
m.attr("MAMBA_FORCE_REINSTALL") = MAMBA_FORCE_REINSTALL;
// CLEAN FLAGS
m.attr("MAMBA_CLEAN_ALL") = MAMBA_CLEAN_ALL;
m.attr("MAMBA_CLEAN_INDEX") = MAMBA_CLEAN_INDEX;
m.attr("MAMBA_CLEAN_PKGS") = MAMBA_CLEAN_PKGS;
m.attr("MAMBA_CLEAN_TARBALLS") = MAMBA_CLEAN_TARBALLS;
m.attr("MAMBA_CLEAN_LOCKS") = MAMBA_CLEAN_LOCKS;
}

View File

@ -29,6 +29,7 @@ from conda.core.package_cache_data import PackageCacheData
from conda.core.prefix_data import PrefixData
from conda.core.solve import get_pinned_specs
from conda.exceptions import (
ArgumentError,
CondaEnvironmentError,
CondaExitZero,
CondaOSError,
@ -45,7 +46,6 @@ from conda.exceptions import (
from conda.gateways.disk.create import mkdir_p
from conda.gateways.disk.delete import delete_trash, path_is_clean, rm_rf
from conda.gateways.disk.test import is_conda_environment
from conda.lock import FileLock
from conda.misc import explicit, touch_nonadmin
from conda.models.match_spec import MatchSpec
@ -53,7 +53,13 @@ import libmambapy as api
import mamba
from mamba import repoquery as repoquery_api
from mamba.mamba_shell_init import shell_init
from mamba.utils import get_installed_jsonfile, init_api_context, load_channels, to_txn
from mamba.utils import (
get_installed_jsonfile,
init_api_context,
load_channels,
lock_file,
to_txn,
)
if sys.version_info < (3, 2):
sys.stdout = codecs.lookup("utf-8")[-1](sys.stdout)
@ -141,7 +147,7 @@ def handle_txn(unlink_link_transaction, prefix, args, newenv, remove_op=False):
raise DryRunExit()
try:
with FileLock(PackageCacheData.first_writable().pkgs_dir):
with lock_file(PackageCacheData.first_writable().pkgs_dir):
unlink_link_transaction.download_and_extract()
if context.download_only:
raise CondaExitZero(
@ -260,7 +266,7 @@ def remove(args, parser):
exit_code = 1
return exit_code
with FileLock(PackageCacheData.first_writable().pkgs_dir):
with lock_file(PackageCacheData.first_writable().pkgs_dir):
package_cache = api.MultiPackageCache(context.pkgs_dirs)
transaction = api.Transaction(solver, package_cache)
downloaded = transaction.prompt(repos)
@ -506,7 +512,7 @@ def install(args, parser, command="install"):
repos = []
with FileLock(context.target_prefix):
with lock_file(context.target_prefix):
prefix_data = api.PrefixData(context.target_prefix)
prefix_data.load()
@ -597,7 +603,7 @@ def install(args, parser, command="install"):
exit_code = 1
return exit_code
with FileLock(PackageCacheData.first_writable().pkgs_dir):
with lock_file(PackageCacheData.first_writable().pkgs_dir):
package_cache = api.MultiPackageCache(context.pkgs_dirs)
transaction = api.Transaction(solver, package_cache)
mmb_specs, to_link, to_unlink = transaction.to_conda()
@ -616,7 +622,7 @@ def install(args, parser, command="install"):
if use_mamba_experimental:
if newenv and not isdir(context.target_prefix) and not context.dry_run:
mkdir_p(prefix)
with FileLock(PackageCacheData.first_writable().pkgs_dir):
with lock_file(PackageCacheData.first_writable().pkgs_dir):
transaction.execute(prefix_data)
else:
conda_transaction = to_txn(
@ -735,6 +741,24 @@ def repoquery(args, parser):
print(repoquery_api._repoquery(args.subcmd, args.package_query, pool, fmt))
def clean(args, parser):
if args.locks:
api.Configuration().show_banner = False
api.clean(api.MAMBA_CLEAN_LOCKS)
try:
from importlib import import_module
relative_mod, func_name = args.func.rsplit(".", 1)
module = import_module("conda.cli" + relative_mod, __name__.rsplit(".", 1)[0])
exit_code = getattr(module, func_name)(args, parser)
return exit_code
except ArgumentError as e:
if not args.locks:
raise e
def do_call(args, parser):
relative_mod, func_name = args.func.rsplit(".", 1)
# func_name should always be 'execute'
@ -742,13 +766,14 @@ def do_call(args, parser):
".main_list",
".main_search",
".main_run",
".main_clean",
".main_info",
]:
from importlib import import_module
module = import_module("conda.cli" + relative_mod, __name__.rsplit(".", 1)[0])
exit_code = getattr(module, func_name)(args, parser)
elif relative_mod == ".main_clean":
exit_code = clean(args, parser)
elif relative_mod == ".main_install":
exit_code = install(args, parser, "install")
elif relative_mod == ".main_remove":
@ -771,6 +796,15 @@ def do_call(args, parser):
return exit_code
def configure_clean_locks(sub_parsers):
removal_target_options = {
g.title: g for g in sub_parsers.choices["clean"]._action_groups
}["Removal Targets"]
removal_target_options.add_argument(
"-l", "--locks", action="store_true", help="Remove lock files.",
)
def configure_parser_repoquery(sub_parsers):
help_cli = "Query repositories using mamba. "
descr = help_cli
@ -865,6 +899,7 @@ def _wrapped_main(*args, **kwargs):
args = argv
p = generate_parser()
configure_clean_locks(p._subparsers._group_actions[0])
configure_parser_repoquery(p._subparsers._group_actions[0])
args = p.parse_args(args[1:])

View File

@ -8,6 +8,8 @@ import os
import tempfile
import urllib.parse
from collections import OrderedDict
from contextlib import contextmanager
from pathlib import Path
from conda._vendor.boltons.setutils import IndexedSet
from conda.base.constants import ChannelPriority
@ -19,7 +21,6 @@ from conda.core.link import PrefixSetup, UnlinkLinkTransaction
from conda.core.prefix_data import PrefixData
from conda.core.solve import diff_for_unlink_link_precs
from conda.gateways.connection.session import CondaHttpAuth
from conda.lock import FileLock
from conda.models.channel import Channel as CondaChannel
from conda.models.prefix_graph import PrefixGraph
from conda.models.records import PackageRecord
@ -27,6 +28,13 @@ from conda.models.records import PackageRecord
import libmambapy as api
@contextmanager
def lock_file(path):
if Path(path).exists():
lock = api.LockFile(path) # noqa F841
yield
def load_channel(subdir_data, result_container):
if not context.quiet:
print("Getting ", subdir_data.channel.name, subdir_data.channel.platform)
@ -76,7 +84,7 @@ def get_index(
all_channels = list(map(fixup_channel_spec, all_channels))
pkgs_dirs = api.MultiPackageCache(context.pkgs_dirs)
cache_dir = api.create_cache_dir(str(pkgs_dirs.first_writable_path))
api.create_cache_dir(str(pkgs_dirs.first_writable_path))
for channel in api.get_channels(all_channels):
for channel_platform, url in channel.platform_urls(with_credentials=True):
@ -91,7 +99,7 @@ def get_index(
else:
name = channel.platform_url(channel_platform, with_credentials=False)
with FileLock(full_path_cache):
with lock_file(full_path_cache):
sd = api.SubdirData(
name,
full_url,
@ -106,8 +114,7 @@ def get_index(
)
dlist.add(sd)
with FileLock(cache_dir):
is_downloaded = dlist.download(True)
is_downloaded = dlist.download(True)
if not is_downloaded:
raise RuntimeError("Error downloading repodata.")
@ -175,7 +182,7 @@ def load_channels(
)
print("Cache path: ", subdir.cache_path())
with FileLock(subdir.cache_path()):
with lock_file(subdir.cache_path()):
repo = subdir.create_repo(pool)
repo.set_priority(priority, subpriority)