-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
RFC: Add RelocPath
type for userdefined relocatable paths
#56053
base: master
Are you sure you want to change the base?
Changes from all commits
78981a2
9b21aba
df8495f
be62b89
2ebb8e0
88e3d07
c2522e2
a9b6ad9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -3298,14 +3298,22 @@ mutable struct CacheHeaderIncludes | |||||||
const modpath::Vector{String} # seemingly not needed in Base, but used by Revise | ||||||||
end | ||||||||
|
||||||||
function replace_depot_path(path::AbstractString, depots::Vector{String}=normalize_depots_for_relocation()) | ||||||||
function replace_depot_path_impl(path::AbstractString, depots::Vector{String}=normalize_depots_for_relocation()) | ||||||||
the_depot = nothing | ||||||||
reloc_path = path | ||||||||
for depot in depots | ||||||||
if startswith(path, string(depot, Filesystem.pathsep())) || path == depot | ||||||||
path = replace(path, depot => "@depot"; count=1) | ||||||||
reloc_path = replace(path, depot => "@depot"; count=1) | ||||||||
the_depot = depot | ||||||||
break | ||||||||
end | ||||||||
end | ||||||||
return path | ||||||||
return the_depot, reloc_path | ||||||||
end | ||||||||
|
||||||||
function replace_depot_path(path::AbstractString, depots::Vector{String}=normalize_depots_for_relocation()) | ||||||||
_, reloc_path = replace_depot_path_impl(path, depots) | ||||||||
return reloc_path | ||||||||
end | ||||||||
|
||||||||
function normalize_depots_for_relocation() | ||||||||
|
@@ -3333,6 +3341,65 @@ function resolve_depot(inc::AbstractString) | |||||||
return :no_depot_found | ||||||||
end | ||||||||
|
||||||||
""" | ||||||||
Base.RelocPath(path::AbstractString) | ||||||||
|
||||||||
A type to represent a relocatable path. | ||||||||
|
||||||||
Requires `path` to be located within one of `DEPOT_PATH` upon construction. | ||||||||
|
||||||||
An error is thrown if relocation fails. | ||||||||
|
||||||||
# Example | ||||||||
```jldoctest | ||||||||
julia> path1 = joinpath(mktempdir(), "foo"); touch(path1); # set up a file called foo | ||||||||
|
||||||||
julia> pushfirst!(DEPOT_PATH, dirname(path1)); | ||||||||
|
||||||||
julia> relocpath = Base.RelocPath(path1); | ||||||||
|
||||||||
julia> String(relocpath) == path1 | ||||||||
true | ||||||||
|
||||||||
julia> path2 = joinpath(mktempdir(), "foo"); touch(path2); # set up another foo | ||||||||
|
||||||||
julia> pushfirst!(DEPOT_PATH, dirname(path2)); | ||||||||
|
||||||||
julia> String(relocpath) == path2 | ||||||||
true | ||||||||
|
||||||||
julia> path1 != path2 | ||||||||
true | ||||||||
``` | ||||||||
""" | ||||||||
struct RelocPath | ||||||||
subpath::String | ||||||||
function RelocPath(path::AbstractString) | ||||||||
depot, _ = replace_depot_path_impl(path) | ||||||||
if isnothing(depot) | ||||||||
error("Failed to locate $(path) in any of DEPOT_PATH.") | ||||||||
end | ||||||||
subpath = replace(path, depot => ""; count=1) | ||||||||
return new(subpath) | ||||||||
end | ||||||||
end | ||||||||
|
||||||||
function String(r::RelocPath) | ||||||||
for d in DEPOT_PATH | ||||||||
if isdirpath(d) | ||||||||
d = dirname(d) | ||||||||
end | ||||||||
path = string(d, r.subpath) | ||||||||
if ispath(path) | ||||||||
return path | ||||||||
end | ||||||||
end | ||||||||
error("Failed to relocate @depot$(r.subpath) in any of DEPOT_PATH.") | ||||||||
end | ||||||||
|
||||||||
function show(io::IO, r::RelocPath) | ||||||||
print(io, string("RelocPath(\"@depot", r.subpath, "\")")) | ||||||||
end | ||||||||
Comment on lines
+3400
to
+3402
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is pretty inaccurate, since it doesn't support
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about we allow RelocPath to accept paths that are literally There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, as far as the original There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
But it does behave like a What is inaccurate is that |
||||||||
|
||||||||
function _parse_cache_header(f::IO, cachefile::AbstractString) | ||||||||
flags = read(f, UInt8) | ||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
module RelocationTestPkg1 | ||
|
||
const relocpath = Base.RelocPath(@__DIR__) | ||
|
||
greet() = print("Hello World!") | ||
|
||
end # module RelocationTestPkg1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thoughts about using
OncePerProcess
to make it so we only compute the result once:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't love this. What if someone has modified
Base.DEPOT_PATH
during their Julia session?