Skip to content

Commit 79ade14

Browse files
author
KristofferC
committed
ensure sources take prio over manifest information, take 2
1 parent 7302e19 commit 79ade14

File tree

3 files changed

+137
-22
lines changed

3 files changed

+137
-22
lines changed

src/Operations.jl

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -200,19 +200,47 @@ function load_project_deps(
200200
end
201201

202202
for (name::String, uuid::UUID) in project.deps
203-
findfirst(pkg -> pkg.uuid == uuid, pkgs) === nothing || continue # do not duplicate packages
203+
# Check if package already exists in pkgs (from up_load_manifest_info! etc)
204+
existing_idx = findfirst(pkg -> pkg.uuid == uuid, pkgs)
205+
204206
path, repo = get_path_repo(project, project_file, manifest_file, name)
205207
entry = manifest_info(manifest, uuid)
208+
209+
# Clear tree_hash if sources override path or repo
210+
tree_hash = entry === nothing ? nothing :
211+
path !== nothing ? nothing :
212+
repo.source !== nothing || repo.rev !== nothing ? nothing :
213+
entry.tree_hash
214+
final_repo = repo == GitRepo() ? entry.repo : repo
215+
216+
if existing_idx !== nothing
217+
# Package already in pkgs - update it with sources info
218+
existing_pkg = pkgs[existing_idx]
219+
# Update tree_hash if sources override
220+
if path !== nothing || repo.source !== nothing || repo.rev !== nothing
221+
existing_pkg.tree_hash = tree_hash
222+
end
223+
# Update path if from sources
224+
if path !== nothing
225+
existing_pkg.path = path
226+
end
227+
# Update repo if from sources
228+
if repo != GitRepo()
229+
existing_pkg.repo = final_repo
230+
end
231+
continue
232+
end
233+
206234
push!(
207235
pkgs_direct, entry === nothing ?
208236
PackageSpec(; uuid, name, path, repo) :
209237
PackageSpec(;
210238
uuid = uuid,
211239
name = name,
212240
path = path === nothing ? entry.path : path,
213-
repo = repo == GitRepo() ? entry.repo : repo,
241+
repo = final_repo,
214242
pinned = entry.pinned,
215-
tree_hash = entry.tree_hash, # TODO should tree_hash be changed too?
243+
tree_hash = tree_hash,
216244
version = load_version(entry.version, isfixed(entry), preserve),
217245
)
218246
)
@@ -248,24 +276,7 @@ function load_all_deps(
248276
preserve::PreserveLevel = PRESERVE_ALL
249277
)
250278
pkgs = load_manifest_deps(env.manifest, pkgs; preserve = preserve)
251-
# Sources takes presedence over the manifest...
252-
for pkg in pkgs
253-
path, repo = get_path_repo(env.project, env.project_file, env.manifest_file, pkg.name)
254-
if path !== nothing
255-
# Path from [sources] takes precedence - clear tree_hash and repo from manifest
256-
pkg.tree_hash = nothing
257-
pkg.repo = GitRepo() # Clear any repo info
258-
pkg.path = path
259-
end
260-
if repo.source !== nothing
261-
# Repo from [sources] takes precedence - clear path from manifest
262-
pkg.path = nothing
263-
pkg.repo.source = repo.source
264-
end
265-
if repo.rev !== nothing
266-
pkg.repo.rev = repo.rev
267-
end
268-
end
279+
# load_direct_deps will apply sources and update tree_hash via load_project_deps
269280
return load_direct_deps(env, pkgs; preserve = preserve)
270281
end
271282

src/Types.jl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,13 +667,18 @@ function load_workspace_weak_deps(env::EnvCache)
667667
return weakdeps
668668
end
669669

670-
# only hash the deps and compat fields as they are the only fields that affect a resolve
670+
# hash the deps, compat, and sources fields as they affect a resolve
671671
function workspace_resolve_hash(env::EnvCache)
672672
# Handle deps in both [deps] and [weakdeps]
673673
deps = Dict(pkg.name => pkg.uuid for pkg in Pkg.Operations.load_direct_deps(env))
674674
weakdeps = load_workspace_weak_deps(env)
675675
alldeps = merge(deps, weakdeps)
676676
compats = Dict(name => Pkg.Operations.get_compat_workspace(env, name) for (name, uuid) in alldeps)
677+
# Collect sources from project and workspace
678+
sources = copy(env.project.sources)
679+
for (_, proj) in env.workspace
680+
merge!(sources, proj.sources)
681+
end
677682
iob = IOBuffer()
678683
for (name, uuid) in sort!(collect(deps); by = first)
679684
println(iob, name, "=", uuid)
@@ -686,6 +691,13 @@ function workspace_resolve_hash(env::EnvCache)
686691
for (name, compat) in sort!(collect(compats); by = first)
687692
println(iob, name, "=", compat)
688693
end
694+
println(iob)
695+
for (name, source_dict) in sort!(collect(sources); by = first)
696+
# Sort the source attributes for deterministic hashing
697+
for (key, val) in sort!(collect(source_dict); by = first)
698+
println(iob, name, ".", key, "=", val)
699+
end
700+
end
689701
str = String(take!(iob))
690702
return bytes2hex(sha1(str))
691703
end

test/sources.jl

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,98 @@ temp_pkg_dir() do project_path
238238
end
239239
end
240240
end
241+
242+
@testset "changing rev in sources updates project_hash and git-tree-sha1 (#4157)" begin
243+
isolate() do
244+
mktempdir() do tmp
245+
# Create a test package with two commits
246+
test_pkg_dir = joinpath(tmp, "TestPkg")
247+
mkpath(test_pkg_dir)
248+
cd(test_pkg_dir) do
249+
write(
250+
"Project.toml", """
251+
name = "TestPkg"
252+
uuid = "b4017d7c-a742-4580-99f2-e286571e6290"
253+
version = "0.1.0"
254+
"""
255+
)
256+
mkpath("src")
257+
write(
258+
"src/TestPkg.jl", """
259+
module TestPkg
260+
greet() = "Hello, World!"
261+
end
262+
"""
263+
)
264+
run(`git init -q`)
265+
run(`git add .`)
266+
run(`git commit -q -m "Initial commit"`)
267+
first_commit = readchomp(`git rev-parse HEAD`)
268+
# Get tree hash by parsing git log
269+
first_tree_hash = match(r"tree ([0-9a-f]+)", readchomp(`git cat-file -p $first_commit`))[1]
270+
271+
# Make a second commit
272+
write("README.md", "# TestPkg\n")
273+
run(`git add .`)
274+
run(`git commit -q -m "Add README"`)
275+
second_commit = readchomp(`git rev-parse HEAD`)
276+
second_tree_hash = match(r"tree ([0-9a-f]+)", readchomp(`git cat-file -p $second_commit`))[1]
277+
278+
# Create consumer project
279+
consumer_dir = joinpath(tmp, "consumer")
280+
mkpath(consumer_dir)
281+
cd(consumer_dir) do
282+
# Start with first revision
283+
write(
284+
"Project.toml", """
285+
[deps]
286+
TestPkg = "b4017d7c-a742-4580-99f2-e286571e6290"
287+
288+
[sources]
289+
TestPkg = { url = "$test_pkg_dir", rev = "$first_commit" }
290+
"""
291+
)
292+
293+
Pkg.activate(".")
294+
Pkg.resolve()
295+
@test isfile("Manifest.toml")
296+
manifest = Pkg.Types.read_manifest("Manifest.toml")
297+
first_project_hash = manifest.project_hash
298+
299+
# Verify first state
300+
test_pkg_uuid = UUID("b4017d7c-a742-4580-99f2-e286571e6290")
301+
@test haskey(manifest.deps, test_pkg_uuid)
302+
test_pkg_entry = manifest[test_pkg_uuid]
303+
@test test_pkg_entry.tree_hash !== nothing
304+
@test string(test_pkg_entry.tree_hash) == first_tree_hash
305+
@test test_pkg_entry.repo.rev == first_commit
306+
307+
# Change to second revision
308+
write(
309+
"Project.toml", """
310+
[deps]
311+
TestPkg = "b4017d7c-a742-4580-99f2-e286571e6290"
312+
313+
[sources]
314+
TestPkg = { url = "$test_pkg_dir", rev = "$second_commit" }
315+
"""
316+
)
317+
318+
Pkg.resolve()
319+
manifest = Pkg.Types.read_manifest("Manifest.toml")
320+
second_project_hash = manifest.project_hash
321+
322+
# Verify second state - both project_hash and git-tree-sha1 should change
323+
test_pkg_entry = manifest[test_pkg_uuid]
324+
@test test_pkg_entry.tree_hash !== nothing
325+
@test string(test_pkg_entry.tree_hash) == second_tree_hash
326+
@test test_pkg_entry.repo.rev == second_commit
327+
@test second_project_hash != first_project_hash
328+
end
329+
end
330+
end
331+
end
332+
end
241333
end
242334

243335
end # module

0 commit comments

Comments
 (0)