Skip to content

Remove ArgumentError() in parse_cache_header() when @depot cannot be resolved #51989

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

Merged
merged 2 commits into from
Nov 2, 2023
Merged
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
10 changes: 6 additions & 4 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2718,11 +2718,9 @@ function parse_cache_header(f::IO, cachefile::AbstractString)
chi.filename ∈ srcfiles && push!(keepidx, i)
end
if depot === :no_depot_found
throw(ArgumentError("""
Failed to determine depot from srctext files in cache file $cachefile.
- Make sure you have adjusted DEPOT_PATH in case you relocated depots."""))
@debug("Unable to resolve @depot tag in cache file $cachefile", srcfiles)
elseif depot === :missing_depot_tag
@debug "Missing @depot tag for include dependencies in cache file $cachefile."
@debug("Missing @depot tag for include dependencies in cache file $cachefile.", srcfiles)
else
for inc in includes
inc.filename = replace(inc.filename, r"^@depot" => depot)
Expand Down Expand Up @@ -3275,6 +3273,10 @@ end
end
for chi in includes
f, fsize_req, hash_req, ftime_req = chi.filename, chi.fsize, chi.hash, chi.mtime
if startswith(f, "@depot/")
@debug("Rejecting stale cache file $cachefile because its depot could not be resolved")
return true
end
if !ispath(f)
_f = fixup_stdlib_path(f)
if isfile(_f) && startswith(_f, Sys.STDLIB)
Expand Down
57 changes: 57 additions & 0 deletions test/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1274,3 +1274,60 @@ end
@test_throws ErrorException Base.check_src_module_wrap(p, fpath)
end
end

@testset "relocatable upgrades #51989" begin
mktempdir() do depot
# Create fake `Foo.jl` package with two files:
foo_path = joinpath(depot, "dev", "Foo")
mkpath(joinpath(foo_path, "src"))
open(joinpath(foo_path, "src", "Foo.jl"); write=true) do io
println(io, """
module Foo
include("internal.jl")
end
""")
end
open(joinpath(foo_path, "src", "internal.jl"); write=true) do io
println(io, "const a = \"asd\"")
end
open(joinpath(foo_path, "Project.toml"); write=true) do io
println(io, """
name = "Foo"
uuid = "00000000-0000-0000-0000-000000000001"
version = "1.0.0"
""")
end

# In our depot, `dev` and then `precompile` this `Foo` package.
@test success(addenv(
`$(Base.julia_cmd()) --startup-file=no -e 'import Pkg; Pkg.develop("Foo"); Pkg.precompile(); exit(0)'`,
"JULIA_DEPOT_PATH" => depot,
))

# Get the size of the generated `.ji` file so that we can ensure that it gets altered
foo_compiled_path = joinpath(depot, "compiled", "v$(VERSION.major).$(VERSION.minor)", "Foo")
cache_path = joinpath(foo_compiled_path, only(filter(endswith(".ji"), readdir(foo_compiled_path))))
cache_size = filesize(cache_path)

# Next, remove the dependence on `internal.jl` and delete it:
rm(joinpath(foo_path, "src", "internal.jl"))
open(joinpath(foo_path, "src", "Foo.jl"); write=true) do io
truncate(io, 0)
println(io, """
module Foo
end
""")
end

# Try to load `Foo`; this should trigger recompilation, not an error!
@test success(addenv(
`$(Base.julia_cmd()) --startup-file=no -e 'using Foo; exit(0)'`,
"JULIA_DEPOT_PATH" => depot,
))

# Ensure that there is still only one `.ji` file (it got replaced
# and the file size changed).
@test length(filter(endswith(".ji"), readdir(foo_compiled_path))) == 1
@test filesize(cache_path) != cache_size
end
end