Skip to content

Commit 3ffa542

Browse files
authored
Merge pull request #73 from frankier/set-preference-pkg-not-in-proj
Add (name, uuid) method to set_preferences!(...) for pkgs not in project
2 parents 209a450 + b9bb86e commit 3ffa542

File tree

3 files changed

+70
-41
lines changed

3 files changed

+70
-41
lines changed

src/Preferences.jl

Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,10 @@ function set_preferences!(target_toml::String, pkg_name::String, pairs::Pair{Str
164164
end
165165

166166
"""
167-
set_preferences!(uuid_or_module_or_name, prefs::Pair{String,Any}...;
167+
set_preferences!(uuid_or_module_or_name_or_tuple, prefs::Pair{String,Any}...;
168168
export_prefs=false, active_project_only=true, force=false)
169169
170-
Sets a series of preferences for the given uuid::UUID/module::Module/name::String,
170+
Sets a series of preferences for the given uuid::UUID/module::Module/name::String/uuid_and_name::Tuple{UUID, String),
171171
identified by the pairs passed in as `prefs`. Preferences are loaded from `Project.toml`
172172
and `LocalPreferences.toml` files on the load path, merging values together into a cohesive
173173
view, with preferences taking precedence in `LOAD_PATH` order, just as package resolution
@@ -182,6 +182,9 @@ the merging performed by `load_preference()` due to inheritance of preferences f
182182
elements higher up in the `load_path()`. To control this inheritance, there are two
183183
special values that can be passed to `set_preferences!()`: `nothing` and `missing`.
184184
185+
* When only one of module/name/UUID are passed, the missing information is extracted from the current project, and therefore it must be installed.
186+
On the other hand, the (UUID, name) tuple form can be used to set preferences on a package that is not yet installed in the active project.
187+
It will be added as extra dependency during the process.
185188
* Passing `missing` as the value causes all mappings of the associated key to be removed
186189
from the current level of `LocalPreferences.toml` settings, allowing preferences set
187190
higher in the chain of preferences to pass through. Use this value when you want to
@@ -220,8 +223,33 @@ preference in the active project and adding it as an extra dependency.
220223
"""
221224
function set_preferences! end
222225

223-
function set_preferences!(u::UUID, prefs::Pair{String,<:Any}...; export_prefs=false,
224-
active_project_only::Bool=true, kwargs...)
226+
function _get_project_toml(u, active_project_only)
227+
if active_project_only
228+
project_toml = Base.active_project()
229+
else
230+
project_toml, pkg_name = find_first_project_with_uuid(u)
231+
if project_toml === nothing && pkg_name === nothing
232+
project_toml = Base.active_project()
233+
end
234+
end
235+
236+
# X-ref: https://github.com/JuliaPackaging/Preferences.jl/issues/34
237+
# We need to handle the edge cases where `project_toml` doesn't exist yet
238+
if !isfile(project_toml)
239+
touch(project_toml)
240+
end
241+
return project_toml
242+
end
243+
244+
function set_preferences!((u, pkg_name)::Tuple{UUID, String},
245+
prefs::Pair{String,<:Any}...;
246+
export_prefs=false,
247+
active_project_only::Bool=true,
248+
project_toml=nothing,
249+
kwargs...)
250+
if project_toml === nothing
251+
project_toml = _get_project_toml(u, active_project_only)
252+
end
225253
# If we try to add preferences for a dependency, we need to make sure
226254
# it is listed as a dependency, so if it's not, we'll add it in the
227255
# "extras" section in the `Project.toml`.
@@ -244,43 +272,6 @@ function set_preferences!(u::UUID, prefs::Pair{String,<:Any}...; export_prefs=fa
244272
return project_toml, pkg_name
245273
end
246274

247-
# Get the pkg name from the current environment if we can't find a
248-
# mapping for it in any environment block. This assumes that the name
249-
# mapping should be the same as what was used in when it was loaded.
250-
function get_pkg_name_from_env()
251-
pkg_uuid_matches = filter(d -> d.uuid == u, keys(Base.loaded_modules))
252-
if isempty(pkg_uuid_matches)
253-
return nothing
254-
end
255-
return first(pkg_uuid_matches).name
256-
end
257-
258-
259-
if active_project_only
260-
project_toml = Base.active_project()
261-
else
262-
project_toml, pkg_name = find_first_project_with_uuid(u)
263-
if project_toml === nothing && pkg_name === nothing
264-
project_toml = Base.active_project()
265-
end
266-
end
267-
268-
# X-ref: https://github.com/JuliaPackaging/Preferences.jl/issues/34
269-
# We need to handle the edge cases where `project_toml` doesn't exist yet
270-
if !isfile(project_toml)
271-
touch(project_toml)
272-
end
273-
274-
pkg_name = something(
275-
Base.get_uuid_name(project_toml, u),
276-
get_pkg_name_from_env(),
277-
Some(nothing),
278-
)
279-
# This only occurs if we couldn't find any hint of the given pkg
280-
if pkg_name === nothing
281-
error("Cannot set preferences of an unknown package that is not loaded!")
282-
end
283-
284275
ensure_dep_added(project_toml, u, pkg_name)
285276

286277
# Finally, save the preferences out to either `Project.toml` or
@@ -300,6 +291,40 @@ function set_preferences!(u::UUID, prefs::Pair{String,<:Any}...; export_prefs=fa
300291
end
301292
return set_preferences!(target_toml, pkg_name, prefs...; kwargs...)
302293
end
294+
function set_preferences!(u::UUID, prefs::Pair{String,<:Any}...;
295+
export_prefs=false,
296+
active_project_only::Bool=true,
297+
project_toml=_get_project_toml(u, active_project_only),
298+
kwargs...)
299+
300+
# Get the pkg name from the current environment if we can't find a
301+
# mapping for it in any environment block. This assumes that the name
302+
# mapping should be the same as what was used in when it was loaded.
303+
function get_pkg_name_from_env()
304+
pkg_uuid_matches = filter(d -> d.uuid == u, keys(Base.loaded_modules))
305+
if isempty(pkg_uuid_matches)
306+
return nothing
307+
end
308+
return first(pkg_uuid_matches).name
309+
end
310+
pkg_name = something(
311+
Base.get_uuid_name(project_toml, u),
312+
get_pkg_name_from_env(),
313+
Some(nothing),
314+
)
315+
# This only occurs if we couldn't find any hint of the given pkg
316+
if pkg_name === nothing
317+
error(
318+
"Cannot set preferences of an unknown package that is not loaded! " *
319+
"(Hint: You can set the preference if you pass the name and UUID as a tuple.)"
320+
)
321+
end
322+
set_preferences!((u, pkg_name), prefs...;
323+
export_prefs=export_prefs,
324+
active_project_only=active_project_only,
325+
project_toml=project_toml,
326+
kwargs...)
327+
end
303328
function set_preferences!(m::Module, prefs::Pair{String,<:Any}...; kwargs...)
304329
return set_preferences!(get_uuid(m), prefs...; kwargs...)
305330
end

test/PTest/src/PTest.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ function do_test()
1010
@test @load_preference("dynamic_exported", default = nothing) == "Local preference just exported"
1111

1212
@test @load_preference("set_by_runtests", default = nothing) == "This was set by runtests.jl"
13+
14+
@test load_preference("TOML", "set_by_runtests", nothing) == "This was set by runtests.jl"
1315

1416
# Pkg handling preferences correctly only came into being in v1.8.0:
1517
# X-ref: https://github.com/JuliaLang/Pkg.jl/commit/e7f1659abd7ae93ce2fbaab491873624cd24eb01

test/PTest/test/runtests.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ using Test, PTest, Preferences
22

33
uuid = Base.UUID("8789f892-390a-4776-818f-b9c2b248add9")
44
set_preferences!(uuid, "set_by_runtests" => "This was set by runtests.jl")
5+
uuid = Base.UUID("fa267f1f-6049-4f14-aa54-33bafae1ed76")
6+
set_preferences!((uuid, "TOML"), "set_by_runtests" => "This was set by runtests.jl")
57
PTest.do_test()

0 commit comments

Comments
 (0)