diff --git a/src/Artifacts.jl b/src/Artifacts.jl index 1ee4705fb9..daa5662ac6 100644 --- a/src/Artifacts.jl +++ b/src/Artifacts.jl @@ -265,6 +265,22 @@ function unbind_artifact!(artifacts_toml::String, name::String; return end +if Sys.iswindows() + # check whether symlinks can be made + function check_symlinks() + PlatformEngines.copy_symlinks() === true && return false # for testing + tmpdir = mktempdir() + fpath = joinpath(tmpdir, "f") + touch(fpath) + try + symlink(fpath, joinpath(tmpdir, "s")) + return true + catch + return false + end + end +end + """ download_artifact(tree_hash::SHA1, tarball_url::String, tarball_hash::String; verbose::Bool = false, io::IO=stderr) @@ -314,6 +330,18 @@ function download_artifact( msg = "Tree Hash Mismatch!\n" msg *= " Expected git-tree-sha1: $(bytes2hex(tree_hash.bytes))\n" msg *= " Calculated git-tree-sha1: $(bytes2hex(calc_hash.bytes))" + @static if Sys.iswindows() + if !check_symlinks() + msg *= """ + + Note: Julia cannot create symlinks, which may be the reason for the hash mismatch. + One solution is to activate Developer Mode in Windows, for instructions on how to do that, see: + https://learn.microsoft.com/en-us/gaming/game-bar/guide/developer-mode + An alternative path is to temporarily set `ENV["JULIA_PKG_IGNORE_HASHES"]=true` + to ignore artifact hash mismatches in this session, however this is generally not recommended. + """ + end + end # Since tree hash calculation is still broken on some systems, e.g. Pkg.jl#1860, # and Pkg.jl#2317, we allow setting JULIA_PKG_IGNORE_HASHES=1 to ignore the # error and move the artifact to the expected location and return true diff --git a/test/artifacts.jl b/test/artifacts.jl index cf80f17a01..b6e92166ca 100644 --- a/test/artifacts.jl +++ b/test/artifacts.jl @@ -796,4 +796,26 @@ end end end +if Sys.iswindows() + @testset "installing artifacts when symlinks are copied" begin + # copy symlinks to simulate the typical Microsoft Windows user experience where + # developer mode is not enabled (no admin rights) + withenv("BINARYPROVIDER_COPYDEREF" => "true") do + temp_pkg_dir() do tmpdir + artifacts_toml = joinpath(tmpdir, "Artifacts.toml") + cp(joinpath(@__DIR__, "test_packages", "ArtifactInstallation", "Artifacts.toml"), artifacts_toml) + Pkg.activate(tmpdir) + cts_hash = artifact_hash("collapse_the_symlink", artifacts_toml) + @test !artifact_exists(cts_hash) + @test_throws "Julia cannot create symlinks" Pkg.instantiate() + @test !artifact_exists(cts_hash) + withenv("JULIA_PKG_IGNORE_HASHES"=>1) do + Pkg.instantiate() + @test artifact_exists(cts_hash) + end + end + end + end +end + end # module