-
-
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?
Conversation
What's the idiomatic usage pattern for this look like? |
The example where module MyPkg
const data = RelocPath(joinpath(@__DIR__, "myfile.data"))
function read_data()
path = String(data)
# load from path ...
end
end |
Is this how we get a Path type finally. I'd love that |
EDIT: Given the timeline, I don't think this can make it into 1.12. Maybe we can merge it into master early in 1.13, so that it gets some time to be tested out. |
Should we have a way of constructing a |
FWIW there is already https://juliahub.com/ui/Packages/General/FilePathsBase and https://juliahub.com/ui/Packages/General/FilePaths which provide such types.
I am not sure. |
@vchuravy @gbaraldi and @topolarity Would you be able to review this PR? As far as I can tell, this PR is an improvement compared to #55146, but I'm not particularly familiar with the relevant part of the codebase. |
@staticfloat IIRC, you also worked on the depot-relocatibility code; it would be great if you could review this PR. |
The |
struct RelocPath | ||
subpath::String |
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:
struct RelocPath | |
subpath::String | |
struct RelocPath | |
getpath::OncePerProcess{String} | |
end | |
RelocPath(path::AbstractString) = let | |
depot, _ = replace_depot_path_impl(path) | |
if isnothing(depot) | |
error("Failed to locate $(path) in any of DEPOT_PATH.") | |
end | |
subpath = String(replace(path, depot => ""; count=1)) | |
return RelocPath(OncePerProcess{String}() do | |
for d in DEPOT_PATH | |
if isdirpath(d) | |
d = dirname(d) | |
end | |
local path = string(d, subpath) | |
if ispath(path) | |
return path | |
end | |
end | |
error("Failed to relocate @depot$(subpath) in any of DEPOT_PATH.") | |
end) | |
end | |
String(r::RelocPath) = r.getpath() # dynamically dispatches since getpath isn 't concrete :/ |
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?
function show(io::IO, r::RelocPath) | ||
print(io, string("RelocPath(\"@depot", r.subpath, "\")")) | ||
end |
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.
This is pretty inaccurate, since it doesn't support @depot
function show(io::IO, r::RelocPath) | |
print(io, string("RelocPath(\"@depot", r.subpath, "\")")) | |
end |
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.
How about we allow RelocPath to accept paths that are literally @depot/foo/bar
?
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.
Also, as far as the original show
method goes, I think that the meaning of @depot/
is reasonably easy to understand here.
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.
This is pretty inaccurate, since it doesn't support @depot
But it does behave like a @depot
. (it behaves more like include_dependency
than include
to be precise)
What is inaccurate is that show
assumes that nobody tinkered with DEPOT_PATH
since construction.
Should we just call this |
No strong feelings from my side. |
I also don't feel strongly between We could also do |
xref: https://discourse.julialang.org/t/designing-a-paths-julep/124335 Specifically the |
Hmmm, that sounds slightly different that the |
@fatteneder Can you rebase and resolve the merge conflicts? |
Functionally, there is a difference in the approaches taken here/proposed, but as far as I can tell there's very much overlap in the intended usage. Both fix the linked issue, and in this respect are alternatives. |
Co-authored-by: Dilum Aluthge <[email protected]>
a9b6ad9
to
895e30d
Compare
I'm not sure I follow. I think I am probably misunderstanding what you mean by "project-relative path". I'll try to highlight my confusion. Here's an example use case. Suppose you have two packages, In the Git repo for In the Git repo for module PkgA
const data = RelocPath(joinpath(dirname(@__DIR__), "data", "stuff.data")) # PkgA/data/myfile.data
function f()
path = String(data)
# load from path ...
end
end # module This is based on the example posted in #55146 (comment) and #56053 (comment). In the Git repo for name = "PkgB"
[deps]
PkgA = "..." In the Git repo for module PkgB
import PkgA
function g()
# ...
x = PkgA.f()
* ...
end
end # module Suppose that I am running on On On # myproj/Project.toml
[deps]
PkgB = "..." Now I build So the user extracts the tarball on their The user makes sure that If we hadn't used But we used So, if we use Would the proposed My interpretation of the phrase "project-relative path" was that |
@fatteneder In the current implementation in this PR, in the It occurs to me that, for correctness purposes, we should have more stringent requirements. Instead of only requiring that the This means that at struct RelocPath
subpath::String
checksum::Union{String, Nothing}
end When constructing a artifact_hash = SHA1(GitTools.tree_hash(the_directory)) Which is taken from this section of If the input path is neither a file nor a directory (e.g. it's a symlink), then tbh idk - throw an error maybe? I don't know if that's a real use case that we need to support, at least not in the initial implementation. I think we should allow opting out of this behavior at two different locations:
What do you think? I feel like this would increase our confidence in the correctness of the file or directory that we return. |
I think this makes senses. For I would go for |
We might also want to promote the object that |
The current idea is that it is relative to the parent project of the code file it occurs in. E.g. in RelocPath(joinpath(dirname(@__DIR__), "data", "stuff.data")) you do p"@/data/stuf.data" And the current intent (the Paths proposal is still being written), is that these would behave the same way. |
RelocPath(path)
works by splittingpath
asdepot/subpath
based onDEPOT_PATH
during construction.When using
RelocPath
one explicitly opts into relocation, so it throws whenpath
cannot be split.A relocated path can be queried with
String(r::RelocPath)
, which also throws on failure.Fixes #54430
Alternative to #55146