Skip to content

Commit 31af274

Browse files
authored
respect versions in sysimage (#3002)
1 parent 09064ab commit 31af274

File tree

7 files changed

+109
-4
lines changed

7 files changed

+109
-4
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
Pkg v1.9 Release Notes
2+
=======================
3+
4+
- Pkg will now respect the version of packages put into the sysimage using e.g. PackageCompiler. For example,
5+
if version 1.3.2 of package A is in the sysimage, Pkg will always install that version when adding the package,
6+
or when the packge is installed as a dependency to some other package. This can be disabled by calling `Pkg.respect_sysimage_versions(false)`.
7+
18
Pkg v1.8 Release Notes
29
======================
310

docs/src/api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Pkg.status
4343
Pkg.compat
4444
Pkg.precompile
4545
Pkg.offline
46+
Pkg.respect_sysimage_versions
4647
Pkg.setprotocol!
4748
Pkg.dependencies
4849
Pkg.project

src/Operations.jl

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import ..Artifacts: ensure_artifact_installed, artifact_names, extract_all_hashe
1414
artifact_exists, select_downloadable_artifacts
1515
using Base.BinaryPlatforms
1616
import ...Pkg
17-
import ...Pkg: pkg_server, Registry, pathrepr, can_fancyprint, printpkgstyle, stderr_f, OFFLINE_MODE, UPDATED_REGISTRY_THIS_SESSION
17+
import ...Pkg: pkg_server, Registry, pathrepr, can_fancyprint, printpkgstyle, stderr_f, OFFLINE_MODE, UPDATED_REGISTRY_THIS_SESSION, RESPECT_SYSIMAGE_VERSIONS
1818

1919
#########
2020
# Utils #
@@ -389,6 +389,7 @@ end
389389
get_or_make!(d::Dict{K,V}, k::K) where {K,V} = get!(d, k) do; V() end
390390

391391
const JULIA_UUID = UUID("1222c4b2-2114-5bfd-aeef-88e4692bbb3e")
392+
const PKGORIGIN_HAVE_VERSION = :version in fieldnames(Base.PkgOrigin)
392393
function deps_graph(env::EnvCache, registries::Vector{Registry.RegistryInstance}, uuid_to_name::Dict{UUID,String},
393394
reqs::Resolve.Requires, fixed::Dict{UUID,Resolve.Fixed}, julia_version)
394395
uuids = Set{UUID}()
@@ -456,6 +457,19 @@ function deps_graph(env::EnvCache, registries::Vector{Registry.RegistryInstance}
456457
is_package_downloaded(env.project_file, pkg_spec) || continue
457458
end
458459

460+
# Skip package version that are not the same as external packages in sysimage
461+
if PKGORIGIN_HAVE_VERSION && RESPECT_SYSIMAGE_VERSIONS[] && julia_version == VERSION
462+
pkgid = Base.PkgId(uuid, pkg.name)
463+
if Base.in_sysimage(pkgid)
464+
pkgorigin = get(Base.pkgorigins, pkgid, nothing)
465+
if pkgorigin !== nothing && pkgorigin.version !== nothing
466+
if v != pkgorigin.version
467+
continue
468+
end
469+
end
470+
end
471+
end
472+
459473
all_compat_u[v] = compat_info
460474
union!(uuids, keys(compat_info))
461475
end
@@ -1857,6 +1871,14 @@ function status_compat_info(pkg::PackageSpec, env::EnvCache, regs::Vector{Regist
18571871
max_version == v"0" && return nothing
18581872
pkg.version >= max_version && return nothing
18591873

1874+
pkgid = Base.PkgId(pkg.uuid, pkg.name)
1875+
if PKGORIGIN_HAVE_VERSION && RESPECT_SYSIMAGE_VERSIONS[] && Base.in_sysimage(pkgid)
1876+
pkgorigin = get(Base.pkgorigins, pkgid, nothing)
1877+
if pkgorigin !== nothing && pkg.version !== nothing && pkg.version == pkgorigin.version
1878+
return ["sysimage"], max_version, max_version_in_compat
1879+
end
1880+
end
1881+
18601882
# Check compat of project
18611883
if pkg.version == max_version_in_compat && max_version_in_compat != max_version
18621884
return ["compat"], max_version, max_version_in_compat
@@ -2055,6 +2077,8 @@ function print_status(env::EnvCache, old_env::Union{Nothing,EnvCache}, registrie
20552077
printstyled(io, " (<v", max_version, ")"; color=Base.warn_color())
20562078
if packages_holding_back == ["compat"]
20572079
printstyled(io, " [compat]"; color=:light_magenta)
2080+
elseif packages_holding_back == ["sysimage"]
2081+
printstyled(io, " [sysimage]"; color=:light_magenta)
20582082
else
20592083
pkg_str = isempty(packages_holding_back) ? "" : string(": ", join(packages_holding_back, ", "))
20602084
printstyled(io, pkg_str; color=Base.warn_color())

src/Pkg.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ devdir(depot = depots1()) = get(ENV, "JULIA_PKG_DEVDIR", joinpath(depot, "dev"))
3333
envdir(depot = depots1()) = joinpath(depot, "environments")
3434
const UPDATED_REGISTRY_THIS_SESSION = Ref(false)
3535
const OFFLINE_MODE = Ref(false)
36+
const RESPECT_SYSIMAGE_VERSIONS = Ref(true)
3637
# For globally overriding in e.g. tests
3738
const DEFAULT_IO = Ref{Union{IO,Nothing}}(nothing)
3839
stderr_f() = something(DEFAULT_IO[], stderr)
@@ -513,6 +514,19 @@ set the environment variable `JULIA_PKG_OFFLINE` to `"true"`.
513514
"""
514515
offline(b::Bool=true) = (OFFLINE_MODE[] = b; nothing)
515516

517+
"""
518+
Pkg.respect_sysimage_versions(b::Bool=true)
519+
520+
Enable (`b=true`) or disable (`b=false`) respecting versions that are in the
521+
sysimage (enabled by default).
522+
523+
If this option is enabled, Pkg will only install packages that have been put into the sysimage
524+
(e.g. via PackageCompiler) at the version of the package in the sysimage.
525+
Also, trying to add a package at a URL or `develop` a package that is in the sysimage
526+
will error.
527+
"""
528+
respect_sysimage_versions(b::Bool=true) = (RESPECT_SYSIMAGE_VERSIONS[] = b; nothing)
529+
516530
"""
517531
PackageSpec(name::String, [uuid::UUID, version::VersionNumber])
518532
PackageSpec(; name, url, path, subdir, rev, version, mode, level)

src/Resolve/graphtype.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,13 @@ function init_log!(data::GraphData)
624624
else
625625
vspec = range_compressed_versionspec(versions)
626626
vers = logstr(id, vspec)
627+
uuid = data.pkgs[p0]
628+
name = data.uuid_to_name[uuid]
629+
pkgid = Base.PkgId(uuid, name)
627630
msg = "possible versions are: $vers or uninstalled"
631+
if Base.in_sysimage(pkgid)
632+
msg *= " (package in sysimage!)"
633+
end
628634
end
629635
first_entry = get!(rlog.pool, p) do
630636
ResolveLogEntry(rlog.journal, p, "$(logstr(id)) log:")

src/Types.jl

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ using REPL.TerminalMenus
1212

1313
using TOML
1414
import ..Pkg, ..Registry
15-
import ..Pkg: GitTools, depots, depots1, logdir, set_readonly, safe_realpath, pkg_server, stdlib_dir, stdlib_path, isurl, stderr_f
15+
import ..Pkg: GitTools, depots, depots1, logdir, set_readonly, safe_realpath, pkg_server, stdlib_dir, stdlib_path, isurl, stderr_f, RESPECT_SYSIMAGE_VERSIONS
1616
import Base.BinaryPlatforms: Platform
1717
using ..Pkg.Versions
1818

@@ -526,6 +526,18 @@ function devpath(env::EnvCache, name::AbstractString, shared::Bool)
526526
return joinpath(dev_dir, name)
527527
end
528528

529+
function error_if_in_sysimage(pkg::PackageSpec)
530+
RESPECT_SYSIMAGE_VERSIONS[] || return false
531+
if pkg.uuid === nothing
532+
@error "Expected package to have a set UUID, please file a bug report"
533+
return false
534+
end
535+
pkgid = Base.PkgId(pkg.uuid, pkg.name)
536+
if Base.in_sysimage(pkgid)
537+
pkgerror("tried to develop or add a package by URL that is already in the sysimage")
538+
end
539+
end
540+
529541
function handle_repo_develop!(ctx::Context, pkg::PackageSpec, shared::Bool)
530542
# First, check if we can compute the path easily (which requires a given local path or name)
531543
is_local_path = pkg.repo.source !== nothing && !isurl(pkg.repo.source)
@@ -544,6 +556,7 @@ function handle_repo_develop!(ctx::Context, pkg::PackageSpec, shared::Bool)
544556
end
545557
if isdir(dev_path)
546558
resolve_projectfile!(ctx.env, pkg, dev_path)
559+
error_if_in_sysimage(pkg)
547560
if is_local_path
548561
pkg.path = isabspath(dev_path) ? dev_path : relative_project_path(ctx.env.project_file, dev_path)
549562
else
@@ -605,6 +618,7 @@ function handle_repo_develop!(ctx::Context, pkg::PackageSpec, shared::Bool)
605618
if !has_uuid(pkg)
606619
resolve_projectfile!(ctx.env, pkg, dev_path)
607620
end
621+
error_if_in_sysimage(pkg)
608622
pkg.path = shared ? dev_path : relative_project_path(ctx.env.project_file, dev_path)
609623
if pkg.repo.subdir !== nothing
610624
pkg.path = joinpath(pkg.path, pkg.repo.subdir)
@@ -735,13 +749,15 @@ function handle_repo_add!(ctx::Context, pkg::PackageSpec)
735749

736750
# If we already resolved a uuid, we can bail early if this package is already installed at the current tree_hash
737751
if has_uuid(pkg)
752+
error_if_in_sysimage(pkg)
738753
version_path = Pkg.Operations.source_path(ctx.env.project_file, pkg, ctx.julia_version)
739754
isdir(version_path) && return false
740755
end
741756

742757
temp_path = mktempdir()
743758
GitTools.checkout_tree_to_path(repo, tree_hash_object, temp_path)
744-
package = resolve_projectfile!(ctx.env, pkg, temp_path)
759+
resolve_projectfile!(ctx.env, pkg, temp_path)
760+
error_if_in_sysimage(pkg)
745761

746762
# Now that we are fully resolved (name, UUID, tree_hash, repo.source, repo.rev), we can finally
747763
# check to see if the package exists at its canonical path.

test/new.jl

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ end
561561
Pkg.add("Markdown")
562562
Pkg.add("Markdown")
563563
Pkg.dependencies(markdown_uuid) do pkg
564-
pkg.name == "Markdown"
564+
@test pkg.name == "Markdown"
565565
end
566566
@test haskey(Pkg.project().dependencies, "Markdown")
567567
end
@@ -2893,4 +2893,41 @@ end
28932893
end
28942894
end
28952895

2896+
if :version in fieldnames(Base.PkgOrigin)
2897+
@testset "sysimage functionality" begin
2898+
old_sysimage_modules = copy(Base._sysimage_modules)
2899+
old_pkgorigins = copy(Base.pkgorigins)
2900+
try
2901+
# Fake having a packages in the sysimage.
2902+
json_pkgid = Base.PkgId(json_uuid, "JSON")
2903+
push!(Base._sysimage_modules, json_pkgid)
2904+
Base.pkgorigins[json_pkgid] = Base.PkgOrigin(nothing, nothing, v"0.20.1")
2905+
isolate(loaded_depot=true) do
2906+
Pkg.add("JSON"; io=devnull)
2907+
Pkg.dependencies(json_uuid) do pkg
2908+
pkg.version == v"0.20.1"
2909+
end
2910+
io = IOBuffer()
2911+
Pkg.status(; outdated=true, io=io)
2912+
str = String(take!(io))
2913+
@test occursin("⌅ [682c06a0] JSON v0.20.1", str)
2914+
@test occursin("[sysimage]", str)
2915+
2916+
@test_throws PkgError Pkg.add(name="JSON", rev="master"; io=devnull)
2917+
@test_throws PkgError Pkg.develop("JSON"; io=devnull)
2918+
2919+
Pkg.respect_sysimage_versions(false)
2920+
Pkg.add("JSON"; io=devnull)
2921+
Pkg.dependencies(json_uuid) do pkg
2922+
pkg.version != v"0.20.1"
2923+
end
2924+
end
2925+
finally
2926+
copy!(Base._sysimage_modules, old_sysimage_modules)
2927+
copy!(Base.pkgorigins, old_pkgorigins)
2928+
Pkg.respect_sysimage_versions(true)
2929+
end
2930+
end
2931+
end
2932+
28962933
end #module

0 commit comments

Comments
 (0)