Skip to content

Commit e2f4632

Browse files
Merge pull request #4036 from JuliaLang/backports-release-1.10
2 parents edfa2ed + 69da354 commit e2f4632

File tree

12 files changed

+129
-23
lines changed

12 files changed

+129
-23
lines changed

docs/src/getting-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ We can see that the `tutorial` environment now contains `Example` and `JSON`.
154154
If you have the same
155155
package (at the same version) installed in multiple environments, the package
156156
will only be downloaded and stored on the hard drive once. This makes environments
157-
very lightweight and effectively free to create. Only using the default
157+
very lightweight and effectively free to create. Using only the default
158158
environment with a huge number of packages in it is a common beginners mistake in
159159
Julia. Learning how to use environments effectively will improve your experience with
160160
Julia packages.

src/Artifacts.jl

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,42 @@ Either rename the directory at `temp_dir` to `new_path` and set it to read-only
6565
or if `new_path` artifact already exists try to do nothing.
6666
"""
6767
function _mv_temp_artifact_dir(temp_dir::String, new_path::String)::Nothing
68-
if !isdir(new_path)
68+
# Sometimes a rename can fail because the temp_dir is locked by
69+
# anti-virus software scanning the new files.
70+
# In this case we want to sleep and try again.
71+
# I am using the list of error codes to retry from:
72+
# https://github.com/isaacs/node-graceful-fs/blob/234379906b7d2f4c9cfeb412d2516f42b0fb4953/polyfills.js#L87
73+
# Retry for up to about 60 seconds by retrying 20 times with exponential backoff.
74+
retry = 0
75+
max_num_retries = 20 # maybe this should be configurable?
76+
sleep_amount = 0.01 # seconds
77+
max_sleep_amount = 5.0 # seconds
78+
while true
79+
isdir(new_path) && return
6980
# This next step is like
7081
# `mv(temp_dir, new_path)`.
7182
# However, `mv` defaults to `cp` if `rename` returns an error.
7283
# `cp` is not atomic, so avoid the potential of calling it.
7384
err = ccall(:jl_fs_rename, Int32, (Cstring, Cstring), temp_dir, new_path)
74-
# Ignore rename error, but ensure `new_path` exists.
75-
if !isdir(new_path)
76-
error("$(repr(new_path)) could not be made")
85+
if err 0
86+
# rename worked
87+
chmod(new_path, filemode(dirname(new_path)))
88+
set_readonly(new_path)
89+
return
90+
else
91+
# Ignore rename error if `new_path` exists.
92+
isdir(new_path) && return
93+
if retry < max_num_retries && err (Base.UV_EACCES, Base.UV_EPERM, Base.UV_EBUSY)
94+
sleep(sleep_amount)
95+
sleep_amount = min(sleep_amount*2.0, max_sleep_amount)
96+
retry += 1
97+
else
98+
Base.uv_error("rename of $(repr(temp_dir)) to $(repr(new_path))", err)
99+
end
77100
end
78101
chmod(new_path, filemode(dirname(new_path)))
79102
set_readonly(new_path)
80103
end
81-
nothing
82104
end
83105

84106
"""
@@ -485,7 +507,7 @@ function with_show_download_info(f, io, name, quiet_download)
485507
if !quiet_download
486508
fancyprint && print(io, "\033[1A") # move cursor up one line
487509
fancyprint && print(io, "\033[2K") # clear line
488-
if success
510+
if success
489511
fancyprint && printpkgstyle(io, :Downloaded, "artifact: $name")
490512
else
491513
printpkgstyle(io, :Failure, "artifact: $name", color = :red)

src/MiniProgressBars.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function show_progress(io::IO, p::MiniProgressBar; termwidth=nothing, carriagere
4040
return
4141
end
4242
t = time()
43-
if p.has_shown && (t - p.time_shown) < PROGRESS_BAR_TIME_GRANULARITY[]
43+
if !p.always_reprint && p.has_shown && (t - p.time_shown) < PROGRESS_BAR_TIME_GRANULARITY[]
4444
return
4545
end
4646
p.time_shown = t

src/Operations.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2210,6 +2210,9 @@ function status_ext_info(pkg::PackageSpec, env::EnvCache)
22102210
# Check if deps are loaded
22112211
extdeps_info= Tuple{String, Bool}[]
22122212
for extdep in extdeps
2213+
haskey(weakdepses, extdep) ||
2214+
pkgerror(isnothing(pkg.name) ? "M" : "$(pkg.name) has a m",
2215+
"alformed Project.toml, the extension package $extdep is not listed in [weakdeps]")
22132216
uuid = weakdepses[extdep]
22142217
loaded = haskey(Base.loaded_modules, Base.PkgId(uuid, extdep))
22152218
push!(extdeps_info, (extdep, loaded))

src/REPLMode/REPLMode.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import REPL: TerminalMenus
1010

1111
import ..casesensitive_isdir, ..OFFLINE_MODE, ..linewrap, ..pathrepr
1212
using ..Types, ..Operations, ..API, ..Registry, ..Resolve
13-
import ..stdout_f, ..stderr_f
13+
import ..stdout_f, ..stderr_f, ..safe_realpath
1414

1515
const TEST_MODE = Ref{Bool}(false)
1616
const PRINTED_REPL_WARNING = Ref{Bool}(false)
@@ -167,7 +167,7 @@ Base.@kwdef mutable struct Statement
167167
end
168168

169169
function lex(cmd::String)::Vector{QString}
170-
replace_comma = (nothing!=match(r"^(add|rm|remove|status|precompile)+\s", cmd))
170+
replace_comma = (nothing!=match(r"^(add|dev|develop|rm|remove|status|precompile)+\s", cmd))
171171
in_doublequote = false
172172
in_singlequote = false
173173
qstrings = QString[]
@@ -497,7 +497,7 @@ function projname(project_file::String)
497497
end
498498
for depot in Base.DEPOT_PATH
499499
envdir = joinpath(depot, "environments")
500-
if startswith(abspath(project_file), abspath(envdir))
500+
if startswith(safe_realpath(project_file), safe_realpath(envdir))
501501
return "@" * name
502502
end
503503
end

src/REPLMode/command_declarations.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ Create a minimal project called `pkgname` in the current folder. For more featur
364364
],
365365
PSA[:name => "precompile",
366366
:api => API.precompile,
367+
:should_splat => false,
367368
:arg_count => 0 => Inf,
368369
:completions => complete_installed_packages,
369370
:description => "precompile all the project dependencies",

src/Registry/Registry.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,15 @@ function update(regs::Vector{RegistrySpec} = RegistrySpec[]; io::IO=stderr_f(),
429429
registry_update_log[string(reg.uuid)] = now()
430430
@label done_tarball_read
431431
else
432+
if reg.name == "General" && Base.get_bool_env("JULIA_PKG_GEN_REG_FMT_CHECK", true)
433+
@info """
434+
The General registry is installed via unpacked tarball.
435+
Consider reinstalling it via the newer faster direct from
436+
tarball format by running:
437+
pkg> registry rm General; registry add General
438+
439+
""" maxlog=1
440+
end
432441
mktempdir() do tmp
433442
try
434443
download_verify_unpack(url, nothing, tmp, ignore_existence = true, io=io)
@@ -447,6 +456,14 @@ function update(regs::Vector{RegistrySpec} = RegistrySpec[]; io::IO=stderr_f(),
447456
end
448457
elseif isdir(joinpath(reg.path, ".git"))
449458
printpkgstyle(io, :Updating, "registry at " * regpath)
459+
if reg.name == "General" && Base.get_bool_env("JULIA_PKG_GEN_REG_FMT_CHECK", true)
460+
@info """
461+
The General registry is installed via git. Consider reinstalling it via
462+
the newer faster direct from tarball format by running:
463+
pkg> registry rm General; registry add General
464+
465+
""" maxlog=1
466+
end
450467
LibGit2.with(LibGit2.GitRepo(reg.path)) do repo
451468
if LibGit2.isdirty(repo)
452469
push!(errors, (regpath, "registry dirty"))

src/Resolve/Resolve.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ function greedysolver(graph::Graph)
341341
return (false, Int[])
342342
elseif old_v1 == spp[p1]
343343
sol[p1] = v1
344+
fill!(gconstr[p1], false)
345+
gconstr[p1][v1] = true
344346
push!(staged_next, p1)
345347
end
346348
end

test/new.jl

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ end
800800
@test Pkg.dependencies()[exuuid].version == v"0.3.0"
801801
@test Pkg.dependencies()[pngjll_uuid].version == v"1.6.37+4"
802802
Pkg.add(Pkg.PackageSpec(;name="JSON", version="0.18.0"); preserve=Pkg.PRESERVE_NONE)
803-
@test Pkg.dependencies()[exuuid].version == v"0.5.3"
803+
@test Pkg.dependencies()[exuuid].version > v"0.3.0"
804804
@test Pkg.dependencies()[json_uuid].version == v"0.18.0"
805805
@test Pkg.dependencies()[pngjll_uuid].version > v"1.6.37+4"
806806
end
@@ -2185,19 +2185,17 @@ end
21852185

21862186
api, arg, opts = first(Pkg.pkg"precompile Foo")
21872187
@test api == Pkg.precompile
2188-
@test arg == "Foo"
2188+
@test arg == ["Foo"]
21892189
@test isempty(opts)
21902190

2191-
api, arg1, arg2, opts = first(Pkg.pkg"precompile Foo Bar")
2191+
api, arg, opts = first(Pkg.pkg"precompile Foo Bar")
21922192
@test api == Pkg.precompile
2193-
@test arg1 == "Foo"
2194-
@test arg2 == "Bar"
2193+
@test arg == ["Foo", "Bar"]
21952194
@test isempty(opts)
21962195

2197-
api, arg1, arg2, opts = first(Pkg.pkg"precompile Foo, Bar")
2196+
api, arg, opts = first(Pkg.pkg"precompile Foo, Bar")
21982197
@test api == Pkg.precompile
2199-
@test arg1 == "Foo"
2200-
@test arg2 == "Bar"
2198+
@test arg == ["Foo", "Bar"]
22012199
@test isempty(opts)
22022200
end
22032201
end

test/pkg.jl

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,9 @@ temp_pkg_dir() do project_path
268268
end
269269

270270
@testset "develop / freeing" begin
271-
Pkg.add(TEST_PKG.name)
271+
Pkg.add(name=TEST_PKG.name, version=v"0.5.3")
272272
old_v = Pkg.dependencies()[TEST_PKG.uuid].version
273+
@test old_v == v"0.5.3"
273274
Pkg.rm(TEST_PKG.name)
274275
mktempdir() do devdir
275276
withenv("JULIA_PKG_DEVDIR" => devdir) do
@@ -298,11 +299,27 @@ temp_pkg_dir() do project_path
298299
touch("deps.jl")
299300
"""
300301
)
302+
exa_proj = joinpath(devdir, TEST_PKG.name, "Project.toml")
303+
proj_str = read(exa_proj, String)
304+
compat_onwards = split(proj_str, "[compat]")[2]
305+
open(exa_proj, "w") do io
306+
println(io, """
307+
name = "Example"
308+
uuid = "$(TEST_PKG.uuid)"
309+
version = "100.0.0"
310+
311+
[compat]
312+
$compat_onwards
313+
""")
314+
end
315+
Pkg.resolve()
316+
@test Pkg.dependencies()[TEST_PKG.uuid].version == v"100.0.0"
301317
Pkg.build(TEST_PKG.name)
302318
@test isfile(joinpath(devdir, TEST_PKG.name, "deps", "deps.jl"))
303319
Pkg.test(TEST_PKG.name)
304320
Pkg.free(TEST_PKG.name)
305-
@test Pkg.dependencies()[TEST_PKG.uuid].version == old_v
321+
@test Pkg.dependencies()[TEST_PKG.uuid].version < v"100.0.0"
322+
@test Pkg.dependencies()[TEST_PKG.uuid].version >= old_v
306323
end
307324
end
308325
end

0 commit comments

Comments
 (0)