From cb2f96aace63f6d60c54b08d3d1bc9f82a15126f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gunnar=20Farneb=C3=A4ck?= Date: Wed, 17 Jun 2020 22:47:45 +0200 Subject: [PATCH 1/2] Add parts of UUID if necessary to make relative package paths case insensitively unique. --- src/register.jl | 8 +++----- src/types.jl | 25 ++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/register.jl b/src/register.jl index ce7f3d9..e076780 100644 --- a/src/register.jl +++ b/src/register.jl @@ -303,7 +303,8 @@ function find_package_in_registry(pkg::Pkg.Types.Project, end @debug("Creating directory for new package $(pkg.name)") - package_path = joinpath(registry_path, package_relpath(pkg)) + package_path = joinpath(registry_path, + package_relpath(registry_data, pkg)) mkpath(package_path) @debug("Adding package UUID to registry") @@ -674,10 +675,7 @@ function register( Registrator tree SHA: $(regtreesha) """ - registry_file = joinpath(registry_path, "Registry.toml") - package_path = joinpath(registry_path, package_relpath(pkg)) - run(pipeline(`$git add -- $package_path`; stdout=devnull)) - run(pipeline(`$git add -- $registry_file`; stdout=devnull)) + run(pipeline(`$git add --all`; stdout=devnull)) run(pipeline(`$git commit -m $message`; stdout=devnull)) # push -f branch to remote diff --git a/src/types.jl b/src/types.jl index 1c6e02c..b57acb4 100644 --- a/src/types.jl +++ b/src/types.jl @@ -150,13 +150,32 @@ end # Not using `joinpath` here since we don't want backslashes in # Registry.toml when running on Windows. -function package_relpath(pkg::Pkg.Types.Project) - string(uppercase(pkg.name[1]), "/", pkg.name) +function package_relpath(registry_data::RegistryData, + pkg::Pkg.Types.Project) + relpath = string(uppercase(pkg.name[1]), "/", pkg.name) + # Check if this path is free from case insensitive collisions with + # previously registered packages. + existing_relpaths = Set(lowercase(package["path"]) + for package in values(registry_data.packages)) + if lowercase(relpath) in existing_relpaths + # Otherwise suffix with a sufficient part of the uuid to make + # the path unique. + uuid = string(pkg.uuid) + for n = 4:length(uuid) + extended_relpath = string(relpath, ".", uuid[1:n]) + if !(lowercase(extended_relpath) in existing_relpaths) + return extended_relpath + end + end + @assert false, "UUID $(uuid) is not unique in registry" + end + + return relpath end function Base.push!(reg::RegistryData, pkg::Pkg.Types.Project) reg.packages[string(pkg.uuid)] = Dict( - "name" => pkg.name, "path" => package_relpath(pkg) + "name" => pkg.name, "path" => package_relpath(reg, pkg) ) reg end From f43e3cdd209693148a383c7b3014b5f8dd007b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gunnar=20Farneb=C3=A4ck?= Date: Mon, 29 Jun 2020 18:19:07 +0200 Subject: [PATCH 2/2] Add tests for relative package paths with parts of UUID. --- src/types.jl | 3 ++- test/regedit.jl | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/types.jl b/src/types.jl index b57acb4..1f4a05b 100644 --- a/src/types.jl +++ b/src/types.jl @@ -162,12 +162,13 @@ function package_relpath(registry_data::RegistryData, # the path unique. uuid = string(pkg.uuid) for n = 4:length(uuid) + uuid[n] == '-' && continue extended_relpath = string(relpath, ".", uuid[1:n]) if !(lowercase(extended_relpath) in existing_relpaths) return extended_relpath end end - @assert false, "UUID $(uuid) is not unique in registry" + @assert false "UUID $(uuid) already exists in registry" end return relpath diff --git a/test/regedit.jl b/test/regedit.jl index b5dffc9..37c8531 100644 --- a/test/regedit.jl +++ b/test/regedit.jl @@ -7,6 +7,7 @@ using RegistryTools: DEFAULT_REGISTRY_URL, using LibGit2 using Pkg.TOML using Pkg.Types: Project +using UUIDs using Test @@ -763,4 +764,61 @@ end end end +@testset "Relative Path" begin + registry_data = RegistryTools.RegistryData( + "BlankRegistry", "d4e2f5cd-0f48-4704-9988-f1754e755b45") + + packages = [("Example", + "7876af07-990d-54b4-ab0e-23690620f79a", + "E/Example"), + ("example", + "0000af07-990d-54b4-ab0e-23690620f79a", + "E/example.0000"), + ("eXampLe", + "7800af07-990d-54b4-ab0e-23690620f79a", + "E/eXampLe.7800"), + ("exAmPlE", + "7876a007-990d-54b4-ab0e-23690620f79a", + "E/exAmPlE.7876"), + ("EXAMPLE", + "7876af07-990d-54b4-ab0e-00690620f79a", + "E/EXAMPLE.7876a"), + ("example", + "7876af07-990d-54b4-ab0e-23000620f79a", + "E/example.7876af")] + + for (name, uuid, expected_path) in packages + project = Project(Dict("name" => name, "uuid" => uuid)) + push!(registry_data, project) + @test registry_data.packages[uuid]["name"] == name + @test registry_data.packages[uuid]["path"] == expected_path + end + + # Stress the path names. + for i = 8:32 + name, uuid, _ = packages[1] + modified_uuid = string(UUID(xor(UUID(uuid).value, + UInt128(1) << (4 * (32 - i))))) + project = Project(Dict("name" => name, "uuid" => modified_uuid)) + push!(registry_data, project) + relpath = registry_data.packages[modified_uuid]["path"] + uuid_part = split(relpath, ".")[end] + @test startswith(uuid, uuid_part) + @test relpath[end] != '-' + @test length(replace(uuid_part, "-" => "")) == i - 1 + end + + # Keep stressing. This requires all the characters of the uuid in + # the path. + name, uuid, = "Example", "7876af07-990d-54b4-ab0e-23690620f790" + project = Project(Dict("name" => name, "uuid" => uuid)) + push!(registry_data, project) + @test registry_data.packages[uuid]["path"] == "E/Example.$(uuid)" + + # This tries to add the same uuid again and is thus misusing the + # function but adds coverage by reaching an assertion that should + # never fail with correct use. + @test_throws AssertionError push!(registry_data, project) +end + end