Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 39 additions & 11 deletions scripts/develop_sources.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
#!/usr/bin/env julia
#
# Develop the [sources] deps of a sub-project.
# Develop/add the [sources] deps of a sub-project.
#
# On Julia < 1.11 the [sources] table is ignored when an environment is
# resolved/built/tested, so a monorepo sublibrary (e.g. lib/<name>) that relies
# on [sources] to pin its in-repo siblings would otherwise resolve them as
# registered packages. This script restores the 1.11+ behavior on 1.10 (the
# SciML LTS) by Pkg.develop-ing each `path =` or `url =` source. On Julia >=
# 1.11 it is a no-op (the table is honored natively).
# SciML LTS). On Julia >= 1.11 it is a no-op (the table is honored natively).
#
# Local `path =` sources are `Pkg.develop`-ed. Git `url =` sources (with optional
# `rev` / `subdir`) are `Pkg.add`-ed: on Julia 1.10 `Pkg.develop` rejects `rev`
# ("rev argument not supported by `develop`; consider using `add` instead"),
# which previously broke LTS CI for any package that temporarily pins an
# unreleased upstream via `[sources]` URL (e.g. JumpProcesses sourcing
# DiffEqBase from an OrdinaryDiffEq monorepo branch).
#
# The walk is transitive: a developed source dep can itself declare further
# *runtime* [sources] that must also be developed for the environment to load.
Expand All @@ -25,10 +31,10 @@
# include("scripts/develop_sources.jl")
# develop_sources(project_dir)
#
# `develop_sources` activates `project_dir`, computes the source specs to
# develop via `collect_source_specs`, and Pkg.develop-s them. The pure
# source-collection logic is split out so it can be unit-tested without mutating
# any environment.
# `develop_sources` activates `project_dir`, computes the source specs via
# `collect_source_specs`, then `Pkg.develop`s path specs and `Pkg.add`s URL
# specs. The pure source-collection logic is split out so it can be unit-tested
# without mutating any environment.

using Pkg

Expand Down Expand Up @@ -117,17 +123,39 @@ function _collect_source_paths_and_specs(proj::AbstractString)
return paths, specs
end

"""
partition_source_specs(specs) -> (path_specs, url_specs)

Split `PackageSpec`s from `collect_source_specs` into local `path` specs
(`Pkg.develop`) and git `url` specs (`Pkg.add`, which accepts `rev`/`subdir`
on Julia 1.10).
"""
function partition_source_specs(specs)
path_specs = Pkg.PackageSpec[]
url_specs = Pkg.PackageSpec[]
for s in specs
if s.path !== nothing
push!(path_specs, s)
elseif s.url !== nothing
push!(url_specs, s)
end
end
return path_specs, url_specs
end

"""
develop_sources(proj)

Activate `proj` and, on Julia < 1.11, `Pkg.develop` its `[sources]` deps
(see `collect_source_specs`). No-op on Julia >= 1.11.
Activate `proj` and, on Julia < 1.11, install its `[sources]` deps (see
`collect_source_specs`): `Pkg.develop` for `path =` entries, `Pkg.add` for
`url =` entries. No-op on Julia >= 1.11.
"""
function develop_sources(proj::AbstractString)
Pkg.activate(proj)
VERSION < v"1.11.0-DEV.0" || return nothing
specs = collect_source_specs(proj)
isempty(specs) || Pkg.develop(specs)
path_specs, url_specs = partition_source_specs(collect_source_specs(proj))
isempty(path_specs) || Pkg.develop(path_specs)
isempty(url_specs) || Pkg.add(url_specs)
return nothing
end

Expand Down
7 changes: 7 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ end
@test any(s -> s.name == "UrlDep" && s.url == "https://example.com/runtime.git" && s.rev == "main", url_specs)
@test any(s -> s.name == "TestOnlyUrl" && s.url == "https://example.com/test-only.git", url_specs)
@test !any(s -> s.name == "NestedTestOnly", url_specs)

# Julia 1.10 Pkg.develop rejects `rev`; URL specs must be Pkg.add-ed.
path_specs, partitioned_urls = partition_source_specs(specs)
@test Set(filter(!isnothing, getfield.(path_specs, :path))) == Set(paths)
@test isempty(filter(s -> s.url !== nothing, path_specs))
@test Set(getfield.(partitioned_urls, :name)) == Set(["UrlDep", "TestOnlyUrl"])
@test all(s -> s.path === nothing && s.url !== nothing, partitioned_urls)
end

@testset "compute_affected_sublibraries" begin
Expand Down
Loading