From 9dd3999b8d355dc620e0ecc12f2d860932c87f3c Mon Sep 17 00:00:00 2001 From: Hind-M <70631848+Hind-M@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:35:55 +0100 Subject: [PATCH] Fix install using explicit url (#3710) --- .../include/mamba/core/package_fetcher.hpp | 2 + libmamba/src/core/package_fetcher.cpp | 31 +++++++++----- micromamba/tests/test_create.py | 40 +++++++++++++++++++ 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/libmamba/include/mamba/core/package_fetcher.hpp b/libmamba/include/mamba/core/package_fetcher.hpp index ff96d85875..faaec08f2d 100644 --- a/libmamba/include/mamba/core/package_fetcher.hpp +++ b/libmamba/include/mamba/core/package_fetcher.hpp @@ -101,6 +101,8 @@ namespace mamba struct CheckSumParams; + bool is_local_package() const; + bool use_explicit_https_url() const; const std::string& filename() const; std::string channel() const; std::string url_path() const; diff --git a/libmamba/src/core/package_fetcher.cpp b/libmamba/src/core/package_fetcher.cpp index cda35b1be4..80f21d61fd 100644 --- a/libmamba/src/core/package_fetcher.cpp +++ b/libmamba/src/core/package_fetcher.cpp @@ -317,6 +317,19 @@ namespace mamba /******************* * Private methods * *******************/ + bool PackageFetcher::is_local_package() const + { + return util::starts_with(m_package_info.package_url, "file://"); + } + + bool PackageFetcher::use_explicit_https_url() const + { + // This excludes OCI case, which uses explicitly a "oci://" scheme, + // but is resolved later to something starting with `oci_base_url` + constexpr std::string_view oci_base_url = "https://pkg-containers.githubusercontent.com/"; + return util::starts_with(m_package_info.package_url, "https://") + && !util::starts_with(m_package_info.package_url, oci_base_url); + } const std::string& PackageFetcher::filename() const { @@ -325,26 +338,24 @@ namespace mamba std::string PackageFetcher::channel() const { - if (!util::starts_with(m_package_info.package_url, "file://")) - { - return m_package_info.channel; - } - else // local package case + if (is_local_package() || use_explicit_https_url()) { + // Use explicit url or local package path + // to fetch package, leaving the channel empty. return ""; } + return m_package_info.channel; } std::string PackageFetcher::url_path() const { - if (!util::starts_with(m_package_info.package_url, "file://")) - { - return util::concat(m_package_info.platform, '/', m_package_info.filename); - } - else // local package case + if (is_local_package() || use_explicit_https_url()) { + // Use explicit url or local package path + // to fetch package. return m_package_info.package_url; } + return util::concat(m_package_info.platform, '/', m_package_info.filename); } const std::string& PackageFetcher::url() const diff --git a/micromamba/tests/test_create.py b/micromamba/tests/test_create.py index b6bbdd7390..8127b98c10 100644 --- a/micromamba/tests/test_create.py +++ b/micromamba/tests/test_create.py @@ -1169,6 +1169,46 @@ def test_create_with_non_existing_subdir(tmp_home, tmp_root_prefix, tmp_path): helpers.create("-p", env_prefix, "--dry-run", "--json", "conda-forge/noarch::xtensor") +@pytest.mark.parametrize( + "spec", + [ + "https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-main.tar.bz2", + "https://conda.anaconda.org/conda-forge/linux-64/abacus-3.2.4-hb6c440e_0.conda", + ], +) +def test_create_with_explicit_url(tmp_home, tmp_root_prefix, tmp_path, spec): + """Attempts to install a package using an explicit url.""" + empty_root_prefix = tmp_path / "empty-root-create-from-explicit-url" + env_name = "env-create-from-explicit-url" + + os.environ["MAMBA_ROOT_PREFIX"] = str(empty_root_prefix) + + res = helpers.create( + spec, "--no-env", "-n", env_name, "--override-channels", "--json", default_channel=False + ) + assert res["success"] + + pkgs = res["actions"]["LINK"] + if spec.endswith(".tar.bz2"): + assert len(pkgs) == 1 + assert pkgs[0]["name"] == "_libgcc_mutex" + assert pkgs[0]["version"] == "0.1" + assert ( + pkgs[0]["url"] + == "https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-main.tar.bz2" + ) + assert pkgs[0]["channel"] == "https://conda.anaconda.org/conda-forge" + else: + assert len(pkgs) == 1 + assert pkgs[0]["name"] == "abacus" + assert pkgs[0]["version"] == "3.2.4" + assert ( + pkgs[0]["url"] + == "https://conda.anaconda.org/conda-forge/linux-64/abacus-3.2.4-hb6c440e_0.conda" + ) + assert pkgs[0]["channel"] == "https://conda.anaconda.org/conda-forge" + + @pytest.mark.parametrize("shared_pkgs_dirs", [True], indirect=True) def test_create_with_multiple_files(tmp_home, tmp_root_prefix, tmpdir): env_name = "myenv"