Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pixi backend #158

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
matrix:
version:
- '1'
- '1.6'
- '1.9'
os:
- ubuntu-latest
- macOS-latest
Expand All @@ -40,15 +40,23 @@ jobs:
os: ubuntu-latest
arch: x64
backend: 'Null'
- version: '1'
os: ubuntu-latest
arch: x64
backend: SystemPixi
steps:
- uses: actions/checkout@v3
- uses: prefix-dev/setup-pixi@v0
if: ${{ matrix.backend == 'SystemPixi' }}
with:
run-install: false
- uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/cache@v1
- uses: julia-actions/julia-downgrade-compat@v1
if: ${{ matrix.version == '1.6' }}
if: ${{ matrix.version == '1.9' }}
with:
skip: Markdown,Pkg,TOML,Aqua,Test,TestItemRunner,OpenSSL_jll
- uses: julia-actions/julia-buildpkg@v1
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## Unreleased
* Add `SystemPixi` backend to allow using [Pixi](https://pixi.sh/latest/) to install packages.

## 0.2.24 (2024-11-08)
* Add `pip_backend` preference to choose between `pip` and `uv`.
* Add `libstdcxx_ng_version` preference to override automatic version bounds.
Expand Down
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
[compat]
Aqua = "0 - 999"
JSON3 = "1.9"
Markdown = "1.6"
Markdown = "1"
MicroMamba = "0.1.4"
OpenSSL_jll = "0 - 999"
Pidfile = "1.3"
Pkg = "1.6"
Pkg = "1.9"
Preferences = "1.3"
Test = "1"
TestItemRunner = "0 - 999"
TOML = "1"
julia = "1.6"
julia = "1.9"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ in more detail.

| Preference | Environment variable | Description |
| ---------- | -------------------- | ----------- |
| `backend` | `JULIA_CONDAPKG_BACKEND` | One of `MicroMamba`, `System`, `Current` or `Null` |
| `backend` | `JULIA_CONDAPKG_BACKEND` | One of `MicroMamba`, `System`, `Current`, `SystemPixi` or `Null` |
| `exe` | `JULIA_CONDAPKG_EXE` | Path to the Conda executable. |
| `offline` | `JULIA_CONDAPKG_OFFLINE` | When `true`, work in offline mode. |
| `env` | `JULIA_CONDAPKG_ENV` | Path to the Conda environment to use. |
Expand All @@ -184,6 +184,8 @@ by setting the `backend` preference to one of the following values:
[MicroMamba.jl](https://github.com/JuliaPy/MicroMamba.jl).
- `System`: Use a pre-installed Conda. If the `exe` preference is set, that is used.
Otherwise we look for `conda`, `mamba` or `micromamba` in your `PATH`.
- `SystemPixi`: Use a pre-installed [Pixi](https://pixi.sh). If the `exe` preference
is set, that is used. Otherwise we look for `pixi` in your `PATH`.
- `Current`: Use the currently activated Conda environment instead of creating a new one.
This backend will only ever install packages, never uninstall. The Conda executable used
is the same as for the System backend. Similar to the default behaviour of
Expand Down
1 change: 1 addition & 0 deletions src/CondaPkg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ end
# backend
backend::Symbol = :NotSet
condaexe::String = ""
pixiexe::String = ""
# resolve
resolved::Bool = false
load_path::Vector{String} = String[]
Expand Down
5 changes: 4 additions & 1 deletion src/PkgREPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,11 @@ const gc_spec = Pkg.REPLMode.CommandSpec(
function run(args)
try
CondaPkg.withenv() do
if args[1] == "conda"
b = CondaPkg.backend()
if b in CondaPkg.CONDA_BACKENDS && args[1] == "conda"
Base.run(CondaPkg.conda_cmd(args[2:end]))
elseif b in CondaPkg.PIXI_BACKENDS && args[1] == "pixi"
Base.run(CondaPkg.pixi_cmd(args[2:end]))
else
Base.run(Cmd(args))
end
Expand Down
41 changes: 35 additions & 6 deletions src/backend.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
"""All valid backends."""
const ALL_BACKENDS = (:MicroMamba, :Null, :System, :Current, :SystemPixi)

"""All backends that use a Conda/Mamba installer."""
const CONDA_BACKENDS = (:MicroMamba, :System, :Current)

"""All backends that use a Pixi installer."""
const PIXI_BACKENDS = (:SystemPixi,)

function backend()
if STATE.backend == :NotSet
backend = getpref(String, "backend", "JULIA_CONDAPKG_BACKEND", "")
Expand Down Expand Up @@ -27,24 +36,44 @@ function backend()
error("not an executable: $exe")
end
end
elseif backend == "SystemPixi"
ok = false
exe2 = Sys.which(exe == "" ? "pixi" : exe)
if exe2 === nothing
if exe == ""
error("could not find a pixi executable")
else
error("not an executable: $exe")
end
end
STATE.backend = :SystemPixi
STATE.pixiexe = exe2
else
error("invalid backend: $backend")
end
end
@assert STATE.backend in ALL_BACKENDS
STATE.backend
end

function conda_cmd(args = ``; io::IO = stderr)
b = backend()
if b == :MicroMamba
MicroMamba.cmd(args, io = io)
elseif b in (:System, :Current)
elseif b in CONDA_BACKENDS
STATE.condaexe == "" && error("this is a bug")
`$(STATE.condaexe) $args`
elseif b == :Null
error(
"Can not run conda command when backend is Null. Manage conda actions outside of julia.",
)
else
@assert false
error("Cannot run conda when backend is $b.")
end
end

function pixi_cmd(args = ``; io::IO = stderr)
b = backend()
if b in PIXI_BACKENDS
STATE.pixiexe == "" && error("this is a bug")
`$(STATE.pixiexe) $args`
else
error("Cannot run pixi when backend is $b.")
end
end
26 changes: 21 additions & 5 deletions src/deps.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,31 @@ function read_parsed_deps(file)
end

function current_packages()
cmd = conda_cmd(`list -p $(envdir()) --json`)
pkglist = JSON3.read(cmd)
b = backend()
if b in CONDA_BACKENDS
cmd = conda_cmd(`list -p $(envdir()) --json`)
pkglist = JSON3.read(cmd)
elseif b in PIXI_BACKENDS
cmd =
pixi_cmd(`list --manifest-path $(joinpath(STATE.meta_dir, "pixi.toml")) --json`)
pkglist = JSON3.read(cmd)
pkglist = [pkg for pkg in pkglist if pkg.kind == "conda"]
end
Dict(normalise_pkg(pkg.name) => pkg for pkg in pkglist)
end

function current_pip_packages()
pkglist = withenv() do
cmd = `$(which("pip")) list --format=json`
JSON3.read(cmd)
b = backend()
if b in CONDA_BACKENDS
pkglist = withenv() do
cmd = `$(which("pip")) list --format=json`
JSON3.read(cmd)
end
elseif b in PIXI_BACKENDS
cmd =
pixi_cmd(`list --manifest-path $(joinpath(STATE.meta_dir, "pixi.toml")) --json`)
pkglist = JSON3.read(cmd)
pkglist = [pkg for pkg in pkglist if pkg.kind == "pypi"]
end
Dict(normalise_pip_pkg(pkg.name) => pkg for pkg in pkglist)
end
Expand Down
12 changes: 8 additions & 4 deletions src/env.jl
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,13 @@ end
Remove unused packages and caches.
"""
function gc(; io::IO = stderr)
backend() == :Null && return
resolve()
cmd = conda_cmd(`clean -y --all`, io = io)
_run(io, cmd, "Removing unused caches")
b = backend()
if b in CONDA_BACKENDS
resolve()
cmd = conda_cmd(`clean -y --all`, io = io)
_run(io, cmd, "Removing unused caches")
else
_log(io, "GC does nothing with the $b backend.")
end
return
end
11 changes: 10 additions & 1 deletion src/meta.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ information about the most recent resolve.
"""

# increment whenever the metadata format changes
const META_VERSION = 13
const META_VERSION = 14

@kwdef mutable struct Meta
timestamp::Float64
conda_env::String
load_path::Vector{String}
extra_path::Vector{String}
version::VersionNumber
backend::Symbol
packages::Vector{PkgSpec}
channels::Vector{ChannelSpec}
pip_packages::Vector{PipPkgSpec}
Expand All @@ -26,6 +27,7 @@ function read_meta(io::IO)
load_path = read_meta(io, Vector{String}),
extra_path = read_meta(io, Vector{String}),
version = read_meta(io, VersionNumber),
backend = read_meta(io, Symbol),
packages = read_meta(io, Vector{PkgSpec}),
channels = read_meta(io, Vector{ChannelSpec}),
pip_packages = read_meta(io, Vector{PipPkgSpec}),
Expand All @@ -43,6 +45,9 @@ function read_meta(io::IO, ::Type{String})
end
String(bytes)
end
function read_meta(io::IO, ::Type{Symbol})
Symbol(read_meta(io, String))
end
function read_meta(io::IO, ::Type{Vector{T}}) where {T}
len = read(io, Int)
ans = Vector{T}()
Expand Down Expand Up @@ -81,6 +86,7 @@ function write_meta(io::IO, meta::Meta)
write_meta(io, meta.load_path)
write_meta(io, meta.extra_path)
write_meta(io, meta.version)
write_meta(io, meta.backend)
write_meta(io, meta.packages)
write_meta(io, meta.channels)
write_meta(io, meta.pip_packages)
Expand All @@ -93,6 +99,9 @@ function write_meta(io::IO, x::String)
write(io, convert(Int, sizeof(x)))
write(io, x)
end
function write_meta(io::IO, x::Symbol)
write_meta(io, String(x))
end
function write_meta(io::IO, x::Vector)
write(io, convert(Int, length(x)))
for item in x
Expand Down
Loading
Loading