Skip to content

Commit 60f47de

Browse files
Merge #1292
1292: Adjustments to `pin` API r=fredrikekre a=00vareladavid #1217 suggests there is some confusing behavior in `pin`. More consistent behavior would be: - `pkg> pin Example@x` means "Try to pin the package to the given registered version, if it exists" - error out when either the package or the version is unregistered - `pkg> pin Example` means "Preserve the package at whatever state it happens to be in" - error out for stdlibs since stdlibs can not really be mutated in the way other packages can Co-authored-by: David Varela <00.varela.david@gmail.com>
2 parents ceea345 + dca0fae commit 60f47de

File tree

3 files changed

+43
-18
lines changed

3 files changed

+43
-18
lines changed

src/Operations.jl

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,30 +1072,46 @@ function up(ctx::Context, pkgs::Vector{PackageSpec}, level::UpgradeLevel)
10721072
# TODO what to do about repo packages?
10731073
end
10741074

1075-
function update_package_pin!(pkg::PackageSpec, ::Nothing)
1075+
function update_package_pin!(ctx::Context, pkg::PackageSpec, ::Nothing)
10761076
if pkg.version == VersionSpec() # no version to pin
10771077
pkgerror("Can not `pin` a package which does not exist in the manifest")
10781078
end
1079-
is_stdlib(pkg.uuid) && pkgerror("cannot `pin` stdlibs.")
1079+
if is_stdlib(pkg.uuid)
1080+
pkgerror("`pin` can not be applied to `$(pkg.name)` because it is a stdlib.")
1081+
end
10801082
pkg.pinned = true
10811083
end
10821084

1083-
function update_package_pin!(pkg::PackageSpec, entry::PackageEntry)
1084-
is_stdlib(pkg.uuid) && pkgerror("cannot `pin` stdlibs.")
1085-
!entry.pinned || pkgerror("`$(entry.name)` already pinned, use `free` first.")
1086-
entry.path === nothing || pkgerror("Can not `pin` `dev`ed package")
1085+
function update_package_pin!(ctx::Context, pkg::PackageSpec, entry::PackageEntry)
1086+
if is_stdlib(pkg.uuid)
1087+
pkgerror("`pin` can not be applied to `$(pkg.name)` because it is a stdlib.")
1088+
end
1089+
if entry.pinned && pkg.version == VersionSpec()
1090+
pkgerror("`$(entry.name)` is already pinned. Use `free` to remove a pin.")
1091+
end
1092+
# update pinned package
10871093
pkg.pinned = true
1088-
pkg.version == VersionSpec() && (pkg.version = entry.version) # pin at current version
1089-
pkg.tree_hash = entry.tree_hash
1090-
pkg.repo = entry.repo
1094+
if pkg.version == VersionSpec()
1095+
pkg.version = entry.version # pin at current version
1096+
pkg.repo = entry.repo
1097+
pkg.tree_hash = entry.tree_hash
1098+
pkg.path = entry.path
1099+
else # given explicit registered version
1100+
if entry.repo.url !== nothing || entry.path !== nothing
1101+
# A pin in this case includes an implicit `free` to switch to tracking registered versions
1102+
# First, make sure the package is registered so we have something to free to
1103+
if isempty(registered_paths(ctx.env, pkg.uuid))
1104+
pkgerror("Unable to pin `$(pkg.name)` to an arbitrary version since it could not be found in a registry.")
1105+
end
1106+
end
1107+
end
10911108
end
10921109

10931110
function pin(ctx::Context, pkgs::Vector{PackageSpec})
1094-
foreach(pkg -> update_package_pin!(pkg, manifest_info(ctx.env, pkg.uuid)), pkgs)
1111+
foreach(pkg -> update_package_pin!(ctx, pkg, manifest_info(ctx.env, pkg.uuid)), pkgs)
10951112
load_direct_deps!(ctx, pkgs)
10961113
check_registered(ctx, pkgs)
10971114

1098-
# TODO check that versions exist ? -> I guess resolve_versions should check ?
10991115
resolve_versions!(ctx, pkgs)
11001116
update_manifest!(ctx, pkgs)
11011117

test/api.jl

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module APITests
44

55
using Pkg, Test
6-
import Pkg.Types.PkgError
6+
import Pkg.Types.PkgError, Pkg.Types.ResolverError
77

88
include("utils.jl")
99

@@ -247,12 +247,21 @@ end
247247
end
248248
end
249249

250-
@testset "Pkg.free" begin
251-
# `pin` should not override previous `pin`
250+
@testset "Pkg.pin" begin
251+
# `pin` should detect unregistered packages
252+
temp_pkg_dir() do project_path; with_temp_env() do env_path
253+
Pkg.add(Pkg.PackageSpec(;url="https://github.com/00vareladavid/Unregistered.jl"))
254+
@test_throws PkgError Pkg.pin(Pkg.PackageSpec(;name="Unregistered", version="0.1.0"))
255+
end end
256+
# when dealing with packages tracking a repo of a regsitered package, `pin` should do an implicit free
257+
temp_pkg_dir() do project_path; with_temp_env() do env_path
258+
Pkg.add(Pkg.PackageSpec(;name="Example",rev="master"))
259+
Pkg.pin(Pkg.PackageSpec(;name="Example",version="0.1.0"))
260+
end end
261+
# pin should check for a valid version number
252262
temp_pkg_dir() do project_path; with_temp_env() do env_path
253-
Pkg.add(Pkg.PackageSpec(;name="Example"))
254-
Pkg.pin(Pkg.PackageSpec(;name="Example", version="0.3.0"))
255-
@test_throws PkgError Pkg.pin(Pkg.PackageSpec(;name="Example", version="0.4.0"))
263+
Pkg.add(Pkg.PackageSpec(;name="Example",rev="master"))
264+
@test_throws ResolverError Pkg.pin(Pkg.PackageSpec(;name="Example",version="100.0.0"))
256265
end end
257266
end
258267

test/pkg.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ end
624624
# the following should not error
625625
Pkg.add("UUIDs")
626626
Pkg.test("UUIDs")
627-
@test_throws PkgError("cannot `pin` stdlibs.") Pkg.pin("UUIDs")
627+
@test_throws PkgError("`pin` can not be applied to `UUIDs` because it is a stdlib.") Pkg.pin("UUIDs")
628628
end
629629
end
630630

0 commit comments

Comments
 (0)