From 8395422de41b3947a3417aee4bdc4255af08b25e Mon Sep 17 00:00:00 2001 From: Christopher Rowley Date: Fri, 27 Jan 2023 09:52:55 +0000 Subject: [PATCH 1/2] treat all shared envs uniformly (#74) Co-authored-by: Christopher Doris --- README.md | 7 ++++--- src/resolve.jl | 55 ++++++++++++++++++++++---------------------------- 2 files changed, 28 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 96fae0a..7a465a2 100644 --- a/README.md +++ b/README.md @@ -177,9 +177,10 @@ already available (such as by having previously called `CondaPkg.resolve()`). By default, CondaPkg installs Conda packages into the current project, so that different projects can have different dependencies. If you wish to centralize the Conda environment, -you can set the environment variable `JULIA_CONDAPKG_ENV` to one of: -- `@` for a named shared environment, stored in `~/.julia/conda_environments/`. -- An absolute path. +you can set one of these environment variables: +- `JULIA_CONDAPKG_ENV=@` for a named shared environment, stored in `~/.julia/conda_environments/`. +- `JULIA_CONDAPKG_ENV=` for a shared environment at the given path. +- `JULIA_BACKEND=Current` to use the currently activated Conda environment. **Warning:** If you do this, the versions specified in a per-julia-version `CondaPkg.toml` can become un-synchronized with the packages installed in the shared Conda environment. diff --git a/src/resolve.jl b/src/resolve.jl index 9a2cccf..68583af 100644 --- a/src/resolve.jl +++ b/src/resolve.jl @@ -400,37 +400,30 @@ function resolve(; force::Bool=false, io::IO=stderr, interactive::Bool=false, dr end STATE.resolved = false STATE.load_path = load_path + # find the topmost env in the load_path which depends on CondaPkg + top_env = _resolve_top_env(load_path) + STATE.meta_dir = meta_dir = joinpath(top_env, ".CondaPkg") + conda_env = get(ENV, "JULIA_CONDAPKG_ENV", "") if back === :Current - # use a pre-existing conda environment conda_env = get(ENV, "CONDA_PREFIX", "") - if conda_env == "" - error("CondaPkg is using the Current backend, but you are not in a Conda environment") - end - STATE.meta_dir = meta_dir = joinpath(conda_env, ".JuliaCondaPkg") - STATE.conda_env = conda_env - STATE.shared = shared = true # environment is shared, disallow removing packages + conda_env != "" || error("CondaPkg is using the Current backend, but you are not in a Conda environment") + shared = true + elseif conda_env == "" + conda_env = joinpath(meta_dir, "env") + shared = false + elseif startswith(conda_env, "@") + conda_env_name = conda_env[2:end] + conda_env_name == "" && error("JULIA_CONDAPKG_ENV shared name cannot be empty") + any(c -> c in ('\\', '/', '@', '#'), conda_env_name) && error("JULIA_CONDAPKG_ENV shared name cannot include special characters") + conda_env = joinpath(Base.DEPOT_PATH[1], "conda_environments", conda_env_name) + shared = true else - # find the topmost env in the load_path which depends on CondaPkg - top_env = _resolve_top_env(load_path) - STATE.meta_dir = meta_dir = joinpath(top_env, ".CondaPkg") - conda_env = get(ENV, "JULIA_CONDAPKG_ENV", "") - if conda_env == "" - conda_env = joinpath(meta_dir, "env") - shared = false - elseif startswith(conda_env, "@") - conda_env_name = conda_env[2:end] - conda_env_name == "" && error("JULIA_CONDAPKG_ENV shared name cannot be empty") - any(c -> c in ('\\', '/', '@', '#'), conda_env_name) && error("JULIA_CONDAPKG_ENV shared name cannot include special characters") - conda_env = joinpath(Base.DEPOT_PATH[1], "conda_environments", conda_env_name) - shared = true - else - isabspath(conda_env) || error("JULIA_CONDAPKG_ENV must be an absolute path") - occursin(".CondaPkg", conda_env) && error("JULIA_CONDAPKG_ENV must not be an existing .CondaPkg, select another directory") - shared = true - end - STATE.conda_env = conda_env - STATE.shared = shared + isabspath(conda_env) || error("JULIA_CONDAPKG_ENV must be an absolute path") + occursin(".CondaPkg", conda_env) && error("JULIA_CONDAPKG_ENV must not be an existing .CondaPkg, select another directory") + shared = true end + STATE.conda_env = conda_env + STATE.shared = shared meta_file = joinpath(meta_dir, "meta") lock_file = joinpath(meta_dir, "lock") # grap a file lock so only one process can resolve this environment at a time @@ -467,7 +460,7 @@ function resolve(; force::Bool=false, io::IO=stderr, interactive::Bool=false, dr pip_specs = _resolve_merge_pip_packages(pip_packages) # find what has changed meta = isfile(meta_file) ? open(read_meta, meta_file) : nothing - if (meta === nothing) || (back === :Current) + if meta === nothing removed_pkgs = String[] changed_pkgs = String[] added_pkgs = unique!(String[x.name for x in specs]) @@ -493,7 +486,7 @@ function resolve(; force::Bool=false, io::IO=stderr, interactive::Bool=false, dr end end # install/uninstall packages - if (back === :Current) || (!force && meta !== nothing && _resolve_env_is_clean(conda_env, meta)) + if !force && meta !== nothing && _resolve_env_is_clean(conda_env, meta) # the state is sufficiently clean that we can modify the existing conda environment changed = false if !isempty(removed_pip_pkgs) && !shared @@ -506,12 +499,12 @@ function resolve(; force::Bool=false, io::IO=stderr, interactive::Bool=false, dr changed = true _resolve_conda_remove(io, conda_env, removed_pkgs) end - if !isempty(specs) && (!isempty(added_pkgs) || !isempty(changed_pkgs) || (meta.channels != channels) || changed) + if !isempty(specs) && (!isempty(added_pkgs) || !isempty(changed_pkgs) || (meta.channels != channels) || changed || shared) dry_run && return changed = true _resolve_conda_install(io, conda_env, specs, channels) end - if !isempty(pip_specs) && (!isempty(added_pip_pkgs) || !isempty(changed_pip_pkgs) || changed) + if !isempty(pip_specs) && (!isempty(added_pip_pkgs) || !isempty(changed_pip_pkgs) || changed || shared) dry_run && return changed = true _resolve_pip_install(io, pip_specs, load_path) From dfc75caaf32785c7dce4d24223a0c186d05aff66 Mon Sep 17 00:00:00 2001 From: Christopher Rowley Date: Fri, 27 Jan 2023 10:23:03 +0000 Subject: [PATCH 2/2] include environment in status (#75) Co-authored-by: Christopher Doris --- src/deps.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/deps.jl b/src/deps.jl index 12fac1b..e5af80d 100644 --- a/src/deps.jl +++ b/src/deps.jl @@ -154,6 +154,11 @@ function status(; io::IO=stderr) printstyled(io, "Using the Null backend", color=:yellow) println(io, " (dependencies shown here are not being managed)") end + if resolved + printstyled(io, "Environment", bold=true, color=:cyan) + println(io) + println(io, " ", STATE.conda_env) + end if !isempty(pkgs) printstyled(io, "Packages", bold=true, color=:cyan) println(io)