Skip to content

Commit

Permalink
relocation: account for trailing path separator in depot paths (#55355)
Browse files Browse the repository at this point in the history
Fixes #55340
  • Loading branch information
fatteneder authored Sep 30, 2024
1 parent bb25910 commit a7c5056
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 25 deletions.
26 changes: 16 additions & 10 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3165,23 +3165,29 @@ mutable struct CacheHeaderIncludes
const modpath::Vector{String} # seemingly not needed in Base, but used by Revise
end

function replace_depot_path(path::AbstractString)
for depot in DEPOT_PATH
!isdir(depot) && continue

# Strip extraneous pathseps through normalization.
if isdirpath(depot)
depot = dirname(depot)
end

if startswith(path, depot)
function replace_depot_path(path::AbstractString, depots::Vector{String}=normalize_depots_for_relocation())
for depot in depots
if startswith(path, string(depot, Filesystem.pathsep())) || path == depot
path = replace(path, depot => "@depot"; count=1)
break
end
end
return path
end

function normalize_depots_for_relocation()
depots = String[]
sizehint!(depots, length(DEPOT_PATH))
for d in DEPOT_PATH
isdir(d) || continue
if isdirpath(d)
d = dirname(d)
end
push!(depots, abspath(d))
end
return depots
end

function restore_depot_path(path::AbstractString, depot::AbstractString)
replace(path, r"^@depot" => depot; count=1)
end
Expand Down
17 changes: 13 additions & 4 deletions src/precompile.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,17 @@ void write_srctext(ios_t *f, jl_array_t *udeps, int64_t srctextpos) {
static jl_value_t *replace_depot_func = NULL;
if (!replace_depot_func)
replace_depot_func = jl_get_global(jl_base_module, jl_symbol("replace_depot_path"));
static jl_value_t *normalize_depots_func = NULL;
if (!normalize_depots_func)
normalize_depots_func = jl_get_global(jl_base_module, jl_symbol("normalize_depots_for_relocation"));
ios_t srctext;
jl_value_t *deptuple = NULL;
JL_GC_PUSH2(&deptuple, &udeps);
jl_value_t *deptuple = NULL, *depots = NULL;
JL_GC_PUSH3(&deptuple, &udeps, &depots);
jl_task_t *ct = jl_current_task;
size_t last_age = ct->world_age;
ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
depots = jl_apply(&normalize_depots_func, 1);
ct->world_age = last_age;
for (size_t i = 0; i < len; i++) {
deptuple = jl_array_ptr_ref(udeps, i);
jl_value_t *depmod = jl_fieldref(deptuple, 0); // module
Expand All @@ -60,13 +68,14 @@ void write_srctext(ios_t *f, jl_array_t *udeps, int64_t srctextpos) {
}

jl_value_t **replace_depot_args;
JL_GC_PUSHARGS(replace_depot_args, 2);
JL_GC_PUSHARGS(replace_depot_args, 3);
replace_depot_args[0] = replace_depot_func;
replace_depot_args[1] = abspath;
replace_depot_args[2] = depots;
jl_task_t *ct = jl_current_task;
size_t last_age = ct->world_age;
ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
jl_value_t *depalias = (jl_value_t*)jl_apply(replace_depot_args, 2);
jl_value_t *depalias = (jl_value_t*)jl_apply(replace_depot_args, 3);
ct->world_age = last_age;
JL_GC_POP();

Expand Down
20 changes: 14 additions & 6 deletions src/staticdata_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,16 @@ static int64_t write_dependency_list(ios_t *s, jl_array_t* worklist, jl_array_t
static jl_value_t *replace_depot_func = NULL;
if (!replace_depot_func)
replace_depot_func = jl_get_global(jl_base_module, jl_symbol("replace_depot_path"));
static jl_value_t *normalize_depots_func = NULL;
if (!normalize_depots_func)
normalize_depots_func = jl_get_global(jl_base_module, jl_symbol("normalize_depots_for_relocation"));

jl_value_t *depots = NULL, *prefs_hash = NULL, *prefs_list = NULL;
JL_GC_PUSH2(&depots, &prefs_list);
last_age = ct->world_age;
ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
depots = jl_apply(&normalize_depots_func, 1);
ct->world_age = last_age;

// write a placeholder for total size so that we can quickly seek past all of the
// dependencies if we don't need them
Expand All @@ -765,13 +775,14 @@ static int64_t write_dependency_list(ios_t *s, jl_array_t* worklist, jl_array_t

if (replace_depot_func) {
jl_value_t **replace_depot_args;
JL_GC_PUSHARGS(replace_depot_args, 2);
JL_GC_PUSHARGS(replace_depot_args, 3);
replace_depot_args[0] = replace_depot_func;
replace_depot_args[1] = deppath;
replace_depot_args[2] = depots;
ct = jl_current_task;
size_t last_age = ct->world_age;
ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
deppath = (jl_value_t*)jl_apply(replace_depot_args, 2);
deppath = (jl_value_t*)jl_apply(replace_depot_args, 3);
ct->world_age = last_age;
JL_GC_POP();
}
Expand Down Expand Up @@ -804,9 +815,6 @@ static int64_t write_dependency_list(ios_t *s, jl_array_t* worklist, jl_array_t
write_int32(s, 0); // terminator, for ease of reading

// Calculate Preferences hash for current package.
jl_value_t *prefs_hash = NULL;
jl_value_t *prefs_list = NULL;
JL_GC_PUSH1(&prefs_list);
if (jl_base_module) {
// Toplevel module is the module we're currently compiling, use it to get our preferences hash
jl_value_t * toplevel = (jl_value_t*)jl_get_global(jl_base_module, jl_symbol("__toplevel__"));
Expand Down Expand Up @@ -853,7 +861,7 @@ static int64_t write_dependency_list(ios_t *s, jl_array_t* worklist, jl_array_t
write_int32(s, 0);
write_uint64(s, 0);
}
JL_GC_POP(); // for prefs_list
JL_GC_POP(); // for depots, prefs_list

// write a dummy file position to indicate the beginning of the source-text
pos = ios_pos(s);
Expand Down
34 changes: 29 additions & 5 deletions test/relocatedepot.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

using Test


Expand Down Expand Up @@ -26,26 +28,48 @@ end

if !test_relocated_depot

@testset "insert @depot tag in path" begin
@testset "edge cases when inserting @depot tag in path" begin

# insert @depot only once for first match
test_harness() do
mktempdir() do dir
pushfirst!(DEPOT_PATH, dir)
path = dir*dir
@test Base.replace_depot_path(path) == "@depot"*dir
if Sys.iswindows()
# dirs start with a drive letter instead of a path separator
path = dir*Base.Filesystem.pathsep()*dir
@test Base.replace_depot_path(path) == "@depot"*Base.Filesystem.pathsep()*dir
else
path = dir*dir
@test Base.replace_depot_path(path) == "@depot"*dir
end
end

# 55340
empty!(DEPOT_PATH)
mktempdir() do dir
jlrc = joinpath(dir, "julia-rc2")
jl = joinpath(dir, "julia")
mkdir(jl)
push!(DEPOT_PATH, jl)
@test Base.replace_depot_path(jl) == "@depot"
@test Base.replace_depot_path(string(jl,Base.Filesystem.pathsep())) ==
string("@depot",Base.Filesystem.pathsep())
@test Base.replace_depot_path(jlrc) != "@depot-rc2"
@test Base.replace_depot_path(jlrc) == jlrc
end
end

# deal with and without trailing path separators
test_harness() do
mktempdir() do dir
pushfirst!(DEPOT_PATH, dir)
path = joinpath(dir, "foo")
if isdirpath(DEPOT_PATH[1])
DEPOT_PATH[1] = dirname(DEPOT_PATH[1]) # strip trailing pathsep
end
tag = joinpath("@depot", "") # append a pathsep
tag = string("@depot", Base.Filesystem.pathsep())
@test startswith(Base.replace_depot_path(path), tag)
DEPOT_PATH[1] = joinpath(DEPOT_PATH[1], "") # append a pathsep
DEPOT_PATH[1] = string(DEPOT_PATH[1], Base.Filesystem.pathsep())
@test startswith(Base.replace_depot_path(path), tag)
popfirst!(DEPOT_PATH)
@test !startswith(Base.replace_depot_path(path), tag)
Expand Down

0 comments on commit a7c5056

Please sign in to comment.