Skip to content

Commit 8776c93

Browse files
authored
Merge pull request #4497 from JuliaLang/backports-release-1.13
Backports for 1.13
2 parents 6aae107 + 9265010 commit 8776c93

File tree

17 files changed

+783
-368
lines changed

17 files changed

+783
-368
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Pkg v1.13 Release Notes
22
=======================
33

4+
- `Pkg.test` now respects the `--check-bounds` setting from the parent Julia session instead of forcing `--check-bounds=yes`.
5+
46
- Project.toml environments now support a `readonly` field to mark environments as read-only, preventing modifications.
57
([#4284])
68
- `Pkg.build` now supports an `allow_reresolve` keyword argument to control whether the build process can re-resolve

docs/src/creating-packages.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,20 +297,28 @@ projects = ["test"]
297297
(HelloWorld) pkg> activate ./test
298298
[ Info: activating environment at `~/HelloWorld/test/Project.toml`.
299299
300-
(HelloWorld/test) pkg> add Test
300+
(HelloWorld/test) pkg> dev . # add current package to test dependencies using its path
301+
Resolving package versions...
302+
Updating `~/HelloWorld/test/Project.toml`
303+
[8dfed614] + HelloWorld v0.1.0 `..`
304+
305+
(HelloWorld/test) pkg> add Test # add other test dependencies
301306
Resolving package versions...
302307
Updating `~/HelloWorld/test/Project.toml`
303308
[8dfed614] + Test
304309
```
305310

306311
When using workspaces, the package manager resolves dependencies for all projects in the workspace together, and creates a single `Manifest.toml` next to the base `Project.toml`. This provides better dependency resolution and makes it easier to manage test-specific dependencies.
307312

313+
!!! warning
314+
Unlike some earlier test dependency workflows, this one explicitly requires adding `HelloWorld` (the parent package) to your `test/Project.toml`.
315+
308316
You can now use `Test` in the test script:
309317

310318
```julia-repl
311319
julia> write("test/runtests.jl",
312320
"""
313-
using Test
321+
using HelloWorld, Test
314322
@test 1 == 1
315323
""");
316324

ext/REPLExt/completions.jl

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -78,32 +78,30 @@ function complete_remote_package!(comps, partial; hint::Bool)
7878
name = regpkg.name
7979
name in cmp && continue
8080
if startswith(regpkg.name, partial)
81-
pkg = Registry.registry_info(regpkg)
81+
pkg = Registry.registry_info(reg, regpkg)
8282
Registry.isdeprecated(pkg) && continue
83-
compat_info = Registry.compat_info(pkg)
84-
# Filter versions
85-
for (v, uncompressed_compat) in compat_info
83+
# Check if any non-yanked version is compatible with current Julia
84+
found_compatible_version = false
85+
for v in keys(pkg.version_info)
8686
Registry.isyanked(pkg, v) && continue
8787
# TODO: Filter based on offline mode
88-
is_julia_compat = nothing
89-
for (pkg_uuid, vspec) in uncompressed_compat
90-
if pkg_uuid == JULIA_UUID
91-
is_julia_compat = VERSION in vspec
92-
is_julia_compat && continue
93-
end
94-
end
95-
# Found a compatible version or compat on julia at all => compatible
96-
if is_julia_compat === nothing || is_julia_compat
97-
push!(cmp, name)
98-
# In hint mode the result is only used if there is a single matching entry
99-
# so we can return no matches in case of more than one match
100-
if hint && found_match
101-
return true # true means returned early
102-
end
103-
found_match = true
88+
# Query compressed compat for this version (optimized: only fetch Julia compat)
89+
julia_vspec = Pkg.Registry.query_compat_for_version(pkg, v, JULIA_UUID)
90+
# Found a compatible version or no julia compat at all => compatible
91+
if julia_vspec === nothing || VERSION in julia_vspec
92+
found_compatible_version = true
10493
break
10594
end
10695
end
96+
if found_compatible_version
97+
push!(cmp, name)
98+
# In hint mode the result is only used if there is a single matching entry
99+
# so we can return no matches in case of more than one match
100+
if hint && found_match
101+
return true # true means returned early
102+
end
103+
found_match = true
104+
end
107105
end
108106
end
109107
end

src/API.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,11 +1346,11 @@ function instantiate(
13461346
end
13471347
repo_path = Types.add_repo_cache_path(repo_source)
13481348
let repo_source = repo_source
1349-
LibGit2.with(GitTools.ensure_clone(ctx.io, repo_path, repo_source; isbare = true)) do repo
1349+
LibGit2.with(GitTools.ensure_clone(ctx.io, repo_path, repo_source; isbare = true, depth = 1)) do repo
13501350
# We only update the clone if the tree hash can't be found
13511351
tree_hash_object = tree_hash(repo, string(pkg.tree_hash))
13521352
if tree_hash_object === nothing
1353-
GitTools.fetch(ctx.io, repo, repo_source; refspecs = Types.refspecs)
1353+
GitTools.fetch(ctx.io, repo, repo_source; refspecs = Types.refspecs, depth = LibGit2.Consts.FETCH_DEPTH_UNSHALLOW)
13541354
tree_hash_object = tree_hash(repo, string(pkg.tree_hash))
13551355
end
13561356
if tree_hash_object === nothing

src/Apps/Apps.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ function get_max_version_register(pkg::PackageSpec, regs)
105105
if get(reg, pkg.uuid, nothing) !== nothing
106106
reg_pkg = get(reg, pkg.uuid, nothing)
107107
reg_pkg === nothing && continue
108-
pkg_info = Registry.registry_info(reg_pkg)
108+
pkg_info = Registry.registry_info(reg, reg_pkg)
109109
for (version, info) in pkg_info.version_info
110110
info.yanked && continue
111111
if pkg.version isa VersionNumber
@@ -216,6 +216,9 @@ function add(pkg::PackageSpec)
216216
manifest.deps[pkg.uuid] = entry
217217

218218
_resolve(manifest, pkg.name)
219+
if new === true || (new isa Set{UUID} && pkg.uuid in new)
220+
Pkg.Operations.build_versions(ctx, Set([pkg.uuid]); verbose = true)
221+
end
219222
precompile(pkg.name)
220223

221224
@info "For package: $(pkg.name) installed apps $(join(keys(project.apps), ","))"
@@ -231,7 +234,7 @@ end
231234

232235
function develop(pkg::PackageSpec)
233236
if pkg.path !== nothing
234-
pkg.path == abspath(pkg.path)
237+
pkg.path = abspath(pkg.path)
235238
end
236239
handle_package_input!(pkg)
237240
ctx = app_context()

src/GitTools.jl

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,45 @@ using Printf
1313
use_cli_git() = Base.get_bool_env("JULIA_PKG_USE_CLI_GIT", false)
1414
const RESOLVING_DELTAS_HEADER = "Resolving Deltas:"
1515

16+
# Check if LibGit2 supports shallow clones (requires LibGit2 >= 1.7.0)
17+
# We check both the LibGit2 version and the existence of `isshallow` to ensure
18+
# the shallow clone functionality is available
19+
function supports_shallow_clone()
20+
# This seems buggy on Windows? Get some weird CI errors with it.
21+
if Sys.iswindows()
22+
return false
23+
end
24+
has_version = @static if isdefined(LibGit2, :VERSION)
25+
LibGit2.VERSION >= v"1.7.0"
26+
else
27+
false
28+
end
29+
has_isshallow = isdefined(LibGit2, :isshallow)
30+
return has_version && has_isshallow
31+
end
32+
33+
# Check if a URL is a local path or file:// URL
34+
# Shallow clones are only supported for network protocols (HTTP, HTTPS, Git, SSH)
35+
function is_local_repo(url::AbstractString)
36+
# Check if it's a local filesystem path
37+
ispath(url) && return true
38+
# Check if it uses file:// protocol
39+
startswith(url, "file://") && return true
40+
return false
41+
end
42+
43+
# Check if a repository is a shallow clone
44+
function isshallow(repo::LibGit2.GitRepo)
45+
if supports_shallow_clone() && isdefined(LibGit2, :isshallow)
46+
return LibGit2.isshallow(repo)
47+
else
48+
# Fallback: check for .git/shallow file
49+
repo_path = LibGit2.path(repo)
50+
shallow_file = joinpath(repo_path, "shallow")
51+
return isfile(shallow_file)
52+
end
53+
end
54+
1655
function transfer_progress(progress::Ptr{LibGit2.TransferProgress}, p::Any)
1756
progress = unsafe_load(progress)
1857
@assert haskey(p, :transfer_progress)
@@ -89,11 +128,17 @@ function checkout_tree_to_path(repo::LibGit2.GitRepo, tree::LibGit2.GitObject, p
89128
end
90129
end
91130

92-
function clone(io::IO, url, source_path; header = nothing, credentials = nothing, isbare = false, kwargs...)
131+
function clone(io::IO, url, source_path; header = nothing, credentials = nothing, isbare = false, depth::Integer = 0, kwargs...)
93132
url = String(url)::String
94133
source_path = String(source_path)::String
95134
@assert !isdir(source_path) || isempty(readdir(source_path))
96135
url = normalize_url(url)
136+
137+
# Disable shallow clones for local repos (not supported) or if LibGit2 doesn't support it
138+
if depth > 0 && (is_local_repo(url) || !supports_shallow_clone())
139+
depth = 0
140+
end
141+
97142
printpkgstyle(io, :Cloning, header === nothing ? "git-repo `$url`" : header)
98143
bar = MiniProgressBar(header = "Cloning:", color = Base.info_color())
99144
fancyprint = can_fancyprint(io)
@@ -103,8 +148,10 @@ function clone(io::IO, url, source_path; header = nothing, credentials = nothing
103148
end
104149
return try
105150
if use_cli_git()
106-
args = ["--quiet", url, source_path]
107-
isbare && pushfirst!(args, "--bare")
151+
args = ["--quiet"]
152+
depth > 0 && push!(args, "--depth=$depth")
153+
isbare && push!(args, "--bare")
154+
push!(args, url, source_path)
108155
cmd = `git clone $args`
109156
try
110157
run(pipeline(cmd; stdout = devnull))
@@ -124,7 +171,12 @@ function clone(io::IO, url, source_path; header = nothing, credentials = nothing
124171
LibGit2.Callbacks()
125172
end
126173
mkpath(source_path)
127-
return LibGit2.clone(url, source_path; callbacks, credentials, isbare, kwargs...)
174+
# Only pass depth if shallow clones are supported and depth > 0
175+
if depth > 0
176+
return LibGit2.clone(url, source_path; callbacks, credentials, isbare, depth, kwargs...)
177+
else
178+
return LibGit2.clone(url, source_path; callbacks, credentials, isbare, kwargs...)
179+
end
128180
end
129181
catch err
130182
rm(source_path; force = true, recursive = true)
@@ -149,10 +201,16 @@ function geturl(repo)
149201
end
150202
end
151203

152-
function fetch(io::IO, repo::LibGit2.GitRepo, remoteurl = nothing; header = nothing, credentials = nothing, refspecs = [""], kwargs...)
204+
function fetch(io::IO, repo::LibGit2.GitRepo, remoteurl = nothing; header = nothing, credentials = nothing, refspecs = [""], depth::Integer = 0, kwargs...)
153205
if remoteurl === nothing
154206
remoteurl = geturl(repo)
155207
end
208+
209+
# Disable shallow fetches for local repos (not supported) or if LibGit2 doesn't support it
210+
if depth > 0 && (is_local_repo(remoteurl) || !supports_shallow_clone())
211+
depth = 0
212+
end
213+
156214
fancyprint = can_fancyprint(io)
157215
remoteurl = normalize_url(remoteurl)
158216
printpkgstyle(io, :Updating, header === nothing ? "git-repo `$remoteurl`" : header)
@@ -174,15 +232,23 @@ function fetch(io::IO, repo::LibGit2.GitRepo, remoteurl = nothing; header = noth
174232
return try
175233
if use_cli_git()
176234
let remoteurl = remoteurl
177-
cmd = `git -C $(LibGit2.path(repo)) fetch -q $remoteurl $(only(refspecs))`
235+
args = ["-C", LibGit2.path(repo), "fetch", "-q"]
236+
depth > 0 && push!(args, "--depth=$depth")
237+
push!(args, remoteurl, only(refspecs))
238+
cmd = `git $args`
178239
try
179240
run(pipeline(cmd; stdout = devnull))
180241
catch err
181242
Pkg.Types.pkgerror("The command $(cmd) failed, error: $err")
182243
end
183244
end
184245
else
185-
return LibGit2.fetch(repo; remoteurl, callbacks, credentials, refspecs, kwargs...)
246+
# Only pass depth if shallow clones are supported and depth > 0
247+
if depth > 0
248+
return LibGit2.fetch(repo; remoteurl, callbacks, credentials, refspecs, depth, kwargs...)
249+
else
250+
return LibGit2.fetch(repo; remoteurl, callbacks, credentials, refspecs, kwargs...)
251+
end
186252
end
187253
catch err
188254
err isa LibGit2.GitError || rethrow()

0 commit comments

Comments
 (0)