Skip to content

Commit 9932036

Browse files
committed
Improve the implementation of force_latest_compatible_version
1 parent d4089a2 commit 9932036

File tree

4 files changed

+140
-103
lines changed

4 files changed

+140
-103
lines changed

src/API.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,9 @@ end
311311

312312
function up(ctx::Context, pkgs::Vector{PackageSpec};
313313
level::UpgradeLevel=UPLEVEL_MAJOR, mode::PackageMode=PKGMODE_PROJECT,
314-
update_registry::Bool=true, kwargs...)
314+
update_registry::Bool=true,
315+
skip_writing_project::Bool=false,
316+
kwargs...)
315317
Context!(ctx; kwargs...)
316318
if update_registry
317319
Registry.download_default_registries(ctx.io)
@@ -328,13 +330,13 @@ function up(ctx::Context, pkgs::Vector{PackageSpec};
328330
manifest_resolve!(ctx.env.manifest, pkgs)
329331
ensure_resolved(ctx.env.manifest, pkgs)
330332
end
331-
Operations.up(ctx, pkgs, level)
333+
Operations.up(ctx, pkgs, level; skip_writing_project)
332334
return
333335
end
334336

335337
resolve(; io::IO=stderr_f(), kwargs...) = resolve(Context(;io); kwargs...)
336-
function resolve(ctx::Context; kwargs...)
337-
up(ctx; level=UPLEVEL_FIXED, mode=PKGMODE_MANIFEST, update_registry=false, kwargs...)
338+
function resolve(ctx::Context; skip_writing_project::Bool=false, kwargs...)
339+
up(ctx; level=UPLEVEL_FIXED, mode=PKGMODE_MANIFEST, update_registry=false, skip_writing_project, kwargs...)
338340
return nothing
339341
end
340342

src/Operations.jl

Lines changed: 56 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,16 @@ function set_compat(proj::Project, name::String, compat::String)
177177
proj.compat[name] = Types.Compat(Types.semver_spec(compat), compat)
178178
end
179179

180+
function reset_all_compat!(proj::Project)
181+
for name in keys(proj.compat)
182+
compat = proj.compat[name]
183+
if compat.val != Types.semver_spec(compat.str)
184+
proj.compat[name] = Types.Compat(Types.semver_spec(compat.str), compat.str)
185+
end
186+
end
187+
return nothing
188+
end
189+
180190
function collect_project!(pkg::PackageSpec, path::String,
181191
deps_map::Dict{UUID,Vector{PackageSpec}})
182192
deps_map[pkg.uuid] = PackageSpec[]
@@ -1218,7 +1228,8 @@ function up_load_manifest_info!(pkg::PackageSpec, entry::PackageEntry)
12181228
# `pkg.version` and `pkg.tree_hash` is set by `up_load_versions!`
12191229
end
12201230

1221-
function up(ctx::Context, pkgs::Vector{PackageSpec}, level::UpgradeLevel)
1231+
function up(ctx::Context, pkgs::Vector{PackageSpec}, level::UpgradeLevel;
1232+
skip_writing_project::Bool=false)
12221233
new_git = Set{UUID}()
12231234
# TODO check all pkg.version == VersionSpec()
12241235
# set version constraints according to `level`
@@ -1236,7 +1247,7 @@ function up(ctx::Context, pkgs::Vector{PackageSpec}, level::UpgradeLevel)
12361247
update_manifest!(ctx.env, pkgs, deps_map, ctx.julia_version)
12371248
new_apply = download_source(ctx)
12381249
download_artifacts(ctx.env, julia_version=ctx.julia_version, io=ctx.io)
1239-
write_env(ctx.env) # write env before building
1250+
write_env(ctx.env; skip_writing_project) # write env before building
12401251
show_update(ctx.env; io=ctx.io)
12411252
build_versions(ctx, union(new_apply, new_git))
12421253
end
@@ -1435,19 +1446,30 @@ function sandbox(fn::Function, ctx::Context, target::PackageSpec, target_path::S
14351446
with_temp_env(tmp) do
14361447
temp_ctx = Context()
14371448
temp_ctx.env.project.deps[target.name] = target.uuid
1449+
1450+
if force_latest_compatible_version
1451+
apply_force_latest_compatible_version!(
1452+
temp_ctx;
1453+
target_name = target.name,
1454+
allow_earlier_backwards_compatible_versions,
1455+
)
1456+
end
1457+
14381458
try
1439-
Pkg.resolve(temp_ctx; io=devnull)
1459+
Pkg.resolve(temp_ctx; io=devnull, skip_writing_project=true)
14401460
@debug "Using _parent_ dep graph"
14411461
catch err# TODO
14421462
err isa Resolve.ResolverError || rethrow()
14431463
allow_reresolve || rethrow()
14441464
@debug err
14451465
@warn "Could not use exact versions of packages in manifest, re-resolving"
14461466
temp_ctx.env.manifest = Dict(uuid => entry for (uuid, entry) in temp_ctx.env.manifest if isfixed(entry))
1447-
Pkg.resolve(temp_ctx; io=devnull)
1467+
Pkg.resolve(temp_ctx; io=devnull, skip_writing_project=true)
14481468
@debug "Using _clean_ dep graph"
14491469
end
14501470

1471+
reset_all_compat!(temp_ctx.env.project)
1472+
14511473
# Absolutify stdlibs paths
14521474
for (uuid, entry) in temp_ctx.env.manifest
14531475
if is_stdlib(uuid)
@@ -1456,17 +1478,6 @@ function sandbox(fn::Function, ctx::Context, target::PackageSpec, target_path::S
14561478
end
14571479
write_env(temp_ctx.env, update_undo = false)
14581480

1459-
if force_latest_compatible_version
1460-
result = check_force_latest_compatible_version(
1461-
temp_ctx;
1462-
target_name = target.name,
1463-
allow_earlier_backwards_compatible_versions,
1464-
)
1465-
if !result
1466-
pkgerror("One or more direct dependencies is not at the latest compatible version")
1467-
end
1468-
end
1469-
14701481
# Run sandboxed code
14711482
path_sep = Sys.iswindows() ? ';' : ':'
14721483
withenv(fn, "JULIA_LOAD_PATH" => "@$(path_sep)$(tmp)", "JULIA_PROJECT" => nothing)
@@ -1813,64 +1824,60 @@ function status(env::EnvCache, pkgs::Vector{PackageSpec}=PackageSpec[];
18131824
end
18141825
end
18151826

1816-
function check_force_latest_compatible_version(ctx::Types.Context;
1817-
target_name = nothing,
1818-
allow_earlier_backwards_compatible_versions::Bool = true)
1827+
function apply_force_latest_compatible_version!(ctx::Types.Context;
1828+
target_name = nothing,
1829+
allow_earlier_backwards_compatible_versions::Bool = true)
18191830
direct_deps = load_direct_deps(ctx.env)
18201831
direct_deps_uuids = [dep.uuid for dep in direct_deps]
18211832
uuid_list = filter(!is_stdlib, direct_deps_uuids)
1822-
isempty(uuid_list) && return true
1823-
results = check_force_latest_compatible_version.(
1824-
Ref(ctx),
1825-
uuid_list;
1826-
target_name,
1827-
allow_earlier_backwards_compatible_versions,
1828-
)
1829-
return all(results)
1833+
for uuid in uuid_list
1834+
apply_force_latest_compatible_version!(
1835+
ctx,
1836+
uuid;
1837+
target_name,
1838+
allow_earlier_backwards_compatible_versions,
1839+
)
1840+
end
1841+
return nothing
18301842
end
18311843

1832-
function check_force_latest_compatible_version(ctx::Types.Context,
1833-
uuid::Base.UUID;
1834-
target_name= nothing,
1835-
allow_earlier_backwards_compatible_versions::Bool = true)
1844+
function apply_force_latest_compatible_version!(ctx::Types.Context,
1845+
uuid::Base.UUID;
1846+
target_name= nothing,
1847+
allow_earlier_backwards_compatible_versions::Bool = true)
18361848
dep = ctx.env.manifest[uuid]
18371849
name = dep.name
18381850
active_version = dep.version
18391851
has_compat = haskey(ctx.env.project.compat, name)
18401852
if !has_compat
18411853
if name != target_name
18421854
@warn(
1843-
"Package does not have a [compat] entry",
1855+
"Dependency does not have a [compat] entry",
18441856
name, uuid, active_version, target_name,
18451857
)
18461858
end
1847-
return true
1859+
return nothing
18481860
end
1849-
compat_entry = ctx.env.project.compat[name].val
1861+
old_compat_spec = ctx.env.project.compat[name].val
18501862
latest_compatible_version = get_latest_compatible_version(
18511863
ctx,
18521864
uuid,
1853-
compat_entry,
1865+
old_compat_spec,
18541866
)
18551867
earliest_backwards_compatible_version = get_earliest_backwards_compatible_version(latest_compatible_version)
18561868
if allow_earlier_backwards_compatible_versions
1857-
result = active_version >= earliest_backwards_compatible_version
1869+
version_for_intersect = only_major_minor_patch(earliest_backwards_compatible_version)
18581870
else
1859-
result = active_version >= latest_compatible_version
1860-
end
1861-
if !result
1862-
@error(
1863-
"Package is not at the latest compatible version",
1864-
name,
1865-
uuid,
1866-
compat_entry,
1867-
active_version,
1868-
latest_compatible_version,
1869-
earliest_backwards_compatible_version,
1870-
allow_earlier_backwards_compatible_versions,
1871-
)
1871+
version_for_intersect = only_major_minor_patch(latest_compatible_version)
18721872
end
1873-
return result
1873+
compat_for_intersect = Pkg.Types.semver_spec("$(version_for_intersect)")
1874+
new_compat_spec = Base.intersect(old_compat_spec, compat_for_intersect)
1875+
ctx.env.project.compat[name].val = new_compat_spec
1876+
return nothing
1877+
end
1878+
1879+
function only_major_minor_patch(ver::Base.VersionNumber)
1880+
return Base.VersionNumber(ver.major, ver.minor, ver.patch)
18741881
end
18751882

18761883
function get_earliest_backwards_compatible_version(ver::Base.VersionNumber)

src/Types.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -932,8 +932,9 @@ manifest_info(::Manifest, uuid::Nothing) = nothing
932932
function manifest_info(manifest::Manifest, uuid::UUID)::Union{PackageEntry,Nothing}
933933
return get(manifest, uuid, nothing)
934934
end
935-
function write_env(env::EnvCache; update_undo=true)
936-
if env.project != env.original_project
935+
function write_env(env::EnvCache; update_undo=true,
936+
skip_writing_project::Bool=false)
937+
if (env.project != env.original_project) && (!skip_writing_project)
937938
write_project(env)
938939
end
939940
if env.manifest != env.original_manifest

0 commit comments

Comments
 (0)