diff --git a/Project.toml b/Project.toml index 1ff84cd..4655c8e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,9 +1,10 @@ name = "PkgDeps" uuid = "839e9fc8-855b-5b3c-a3b7-2833d3dd1f59" license = "MIT" -version = "0.1.0" +version = "0.2.0" [deps] +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" diff --git a/src/PkgDeps.jl b/src/PkgDeps.jl index 1323369..81bb844 100644 --- a/src/PkgDeps.jl +++ b/src/PkgDeps.jl @@ -1,52 +1,42 @@ module PkgDeps +using Pkg.Types: VersionNumber, VersionRange using TOML: parsefile using UUIDs export PkgEntry, RegistryInstance -export find_upstream_dependencies, reachable_registries +export find_downstream_dependencies, reachable_registries -struct PkgEntry - path::String - registry_path::String - name::String - uuid::UUID -end +include("pkg_entry.jl") +include("registry_instance.jl") -struct RegistryInstance - path::String - name::String - uuid::UUID - url::Union{String, Nothing} - repo::Union{String, Nothing} - description::Union{String, Nothing} - pkgs::Dict{AbstractString, PkgEntry} -end -function RegistryInstance(path::AbstractString) - d = parsefile(joinpath(path, "Registry.toml")) - pkgs = Dict{AbstractString, PkgEntry}() - - for (uuid, info) in d["packages"] - uuid = UUID(uuid) - info - name = info["name"] - pkgpath = info["path"] - pkg = PkgEntry(pkgpath, path, name, uuid) - pkgs[name] = pkg - end +""" + _get_latest_version(base_path::AbstractString) + +Get the latest VersionNumber for base_path/Versions.toml - return RegistryInstance( - path, - d["name"], - UUID(d["uuid"]), - get(d, "url", nothing), - get(d, "repo", nothing), - get(d, "description", nothing), - pkgs - ) +# Arguments +- `base_path::AbstractString`: Base path to look for Versions.toml + +# Returns +- `VersionNumber`: Highest version number found in base_path/Versions.toml + +# Throws +- `VersionTOMLNotFound`: Versions.toml does not exist at the base_path +""" +function _get_latest_version(base_path::AbstractString) + versions_file_path = joinpath(base_path, "Versions.toml") + + if isfile(versions_file_path) + versions_content = parsefile(versions_file_path) + versions = [VersionNumber(v) for v in collect(keys(versions_content))] + + return first(findmax(versions)) + end end + """ reachable_registries(registry_names::Array) @@ -92,7 +82,7 @@ reachable_registries(registry_name::String; depots::Union{String, Vector{String} """ - find_upstream_dependencies(pkg_name::AbstractString; registries::Array{PkgDeps.RegistryInstance}=reachable_registries()) + find_downstream_dependencies(pkg_name::AbstractString; registries::Array{PkgDeps.RegistryInstance}=reachable_registries()) Find all dependents of `pkg_name` for the current master version. @@ -105,29 +95,38 @@ Find all dependents of `pkg_name` for the current master version. # Returns - `Array{String}`: List of packages which depend on `pkg_name` """ -function find_upstream_dependencies(pkg_name::AbstractString; registries::Array{RegistryInstance}=reachable_registries()) - upstream_dependencies = String[] +function find_downstream_dependencies( + pkg_name::AbstractString; + registries::Array{RegistryInstance}=reachable_registries() +) + downstream_dependencies = String[] for rego in registries for (pkg, v) in rego.pkgs - path = joinpath(v.registry_path, v.path, "Deps.toml") - - if isfile(path) - file_contents = parsefile(path) - - dep_keys = [k for k in collect(keys(file_contents)) if endswith(k, "-0") || k == "0"] - - deps = getindex.(Ref(file_contents), dep_keys) - deps = vcat(collect.(keys.(deps))...) - - if pkg_name in deps - push!(upstream_dependencies, pkg) + base_path = joinpath(v.registry_path, v.path) + deps_file_path = joinpath(base_path, "Deps.toml") + + if isfile(deps_file_path) + deps_content = parsefile(deps_file_path) + dependency_versions = collect(keys(deps_content)) + latest_version = _get_latest_version(base_path) + + # Use the latest_version of pkg, and check to see if pkg_name is in its dependents + for version_range in dependency_versions + if in(latest_version, VersionRange(version_range)) + dependencies = collect(keys(deps_content[version_range])) + + # Check if pkg_name is used in the latest version of pkg + if pkg_name in dependencies + push!(downstream_dependencies, pkg) + end + end end end end end - return upstream_dependencies + return downstream_dependencies end end diff --git a/src/pkg_entry.jl b/src/pkg_entry.jl new file mode 100644 index 0000000..dd7c386 --- /dev/null +++ b/src/pkg_entry.jl @@ -0,0 +1,6 @@ +struct PkgEntry + path::String + registry_path::String + name::String + uuid::UUID +end diff --git a/src/registry_instance.jl b/src/registry_instance.jl new file mode 100644 index 0000000..5ddd044 --- /dev/null +++ b/src/registry_instance.jl @@ -0,0 +1,33 @@ +struct RegistryInstance + path::String + name::String + uuid::UUID + url::Union{String, Nothing} + repo::Union{String, Nothing} + description::Union{String, Nothing} + pkgs::Dict{AbstractString, PkgEntry} +end + +function RegistryInstance(path::AbstractString) + d = parsefile(joinpath(path, "Registry.toml")) + pkgs = Dict{AbstractString, PkgEntry}() + + for (uuid, info) in d["packages"] + uuid = UUID(uuid) + info + name = info["name"] + pkgpath = info["path"] + pkg = PkgEntry(pkgpath, path, name, uuid) + pkgs[name] = pkg + end + + return RegistryInstance( + path, + d["name"], + UUID(d["uuid"]), + get(d, "url", nothing), + get(d, "repo", nothing), + get(d, "description", nothing), + pkgs + ) +end diff --git a/test/resources/registries/Foobar/Case1/Deps.toml b/test/resources/registries/Foobar/Case1/Deps.toml index cef037f..4977338 100644 --- a/test/resources/registries/Foobar/Case1/Deps.toml +++ b/test/resources/registries/Foobar/Case1/Deps.toml @@ -1,2 +1,2 @@ [0] -UpDep = "000eeb74-f857-587a-a816-be5685e97e75" +DownDep = "000eeb74-f857-587a-a816-be5685e97e75" diff --git a/test/resources/registries/Foobar/Case1/Versions.toml b/test/resources/registries/Foobar/Case1/Versions.toml new file mode 100644 index 0000000..61ed410 --- /dev/null +++ b/test/resources/registries/Foobar/Case1/Versions.toml @@ -0,0 +1,2 @@ +["0.0.1"] +git-tree-sha1 = "7bbdd841302ae0708824fa57d77a3e4780097531" diff --git a/test/resources/registries/Foobar/Case2/Deps.toml b/test/resources/registries/Foobar/Case2/Deps.toml index ba36cd3..9548894 100644 --- a/test/resources/registries/Foobar/Case2/Deps.toml +++ b/test/resources/registries/Foobar/Case2/Deps.toml @@ -1,2 +1,2 @@ ["0.1-0"] -UpDep = "000eeb74-f857-587a-a816-be5685e97e75" +DownDep = "000eeb74-f857-587a-a816-be5685e97e75" diff --git a/test/resources/registries/Foobar/Case2/Versions.toml b/test/resources/registries/Foobar/Case2/Versions.toml new file mode 100644 index 0000000..bd9349b --- /dev/null +++ b/test/resources/registries/Foobar/Case2/Versions.toml @@ -0,0 +1,2 @@ +["0.1.0"] +git-tree-sha1 = "7bbdd841302ae0708824fa57d77a3e4780097531" diff --git a/test/resources/registries/General/Case3/Deps.toml b/test/resources/registries/General/Case3/Deps.toml index f03f072..f3fe1c1 100644 --- a/test/resources/registries/General/Case3/Deps.toml +++ b/test/resources/registries/General/Case3/Deps.toml @@ -1,2 +1,2 @@ -["0"] -UpDep = "000eeb74-f857-587a-a816-be5685e97e75" +["1"] +DownDep = "000eeb74-f857-587a-a816-be5685e97e75" diff --git a/test/resources/registries/General/Case3/Versions.toml b/test/resources/registries/General/Case3/Versions.toml new file mode 100644 index 0000000..d2f962b --- /dev/null +++ b/test/resources/registries/General/Case3/Versions.toml @@ -0,0 +1,2 @@ +["1.1.1"] +git-tree-sha1 = "7bbdd841302ae0708824fa57d77a3e4780097531" diff --git a/test/resources/registries/General/Case4/Deps.toml b/test/resources/registries/General/Case4/Deps.toml new file mode 100644 index 0000000..83c8b7e --- /dev/null +++ b/test/resources/registries/General/Case4/Deps.toml @@ -0,0 +1,2 @@ +["0-0.1"] +DownDep = "000eeb74-f857-587a-a816-be5685e97e75" diff --git a/test/resources/registries/General/Case4/Versions.toml b/test/resources/registries/General/Case4/Versions.toml new file mode 100644 index 0000000..36310db --- /dev/null +++ b/test/resources/registries/General/Case4/Versions.toml @@ -0,0 +1,5 @@ +["0.1.0"] +git-tree-sha1 = "7bbdd841302ae0708824fa57d77a3e4780097531" + +["0.2.0"] +git-tree-sha1 = "36895c2e78b43dea83b9fdba6655886c107cdc98" diff --git a/test/resources/registries/General/Registry.toml b/test/resources/registries/General/Registry.toml index 24cb0af..ad67c1b 100644 --- a/test/resources/registries/General/Registry.toml +++ b/test/resources/registries/General/Registry.toml @@ -12,3 +12,4 @@ some amount of consideration when choosing package names. [packages] 000eeb74-f857-587a-a816-be5685e97e75 = { name = "Case3", path = "Case3" } +001eeb74-f857-587a-a816-be5685e97e75 = { name = "Case4", path = "Case4" } diff --git a/test/resources/registries/README.md b/test/resources/registries/README.md new file mode 100644 index 0000000..ed06824 --- /dev/null +++ b/test/resources/registries/README.md @@ -0,0 +1,19 @@ +## Creating test cases +When adding test cases please create another test case in any existing registry. +Include `Deps.toml` and `Versions.toml` files to specify when a package has been dependent +on another. + + +## Overview of Cases + +### Case1 +Single patch pre-1.0 release that has always been dependent on `DownDep`. + +### Case2 +Single minor pre-1.0 release that has always been dependent on `DownDep`. + +### Case3 +Single post-1.0 release that is dependent on `DownDep`. + +### Case4 +Two releases where `DownDep` was previously a depdenency and no longer is. diff --git a/test/runtests.jl b/test/runtests.jl index 8e458db..0e27845 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,7 +1,5 @@ using PkgDeps using Test -# Create some temp package TOML files -# Test that we get them properly depot = joinpath(@__DIR__, "resources") @@ -20,21 +18,22 @@ depot = joinpath(@__DIR__, "resources") end end -@testset "find_upstream_dependencies" begin - @testset "specific registry" begin - foobar_registry = reachable_registries("Foobar"; depots=depot) +@testset "find_downstream_dependencies" begin + foobar_registry = reachable_registries("Foobar"; depots=depot) + all_registries = reachable_registries(; depots=depot) - dependents = find_upstream_dependencies("UpDep"; registries=foobar_registry) + @testset "specific registry" begin + dependents = find_downstream_dependencies("DownDep"; registries=foobar_registry) @test length(dependents) == 2 [@test case in dependents for case in ["Case1", "Case2"]] end @testset "all registries" begin - registries = reachable_registries(; depots=depot) - dependents = find_upstream_dependencies("UpDep"; registries=registries) + dependents = find_downstream_dependencies("DownDep"; registries=all_registries) @test length(dependents) == 3 + @test !("Case4" in dependents) [@test case in dependents for case in ["Case1", "Case2", "Case3"]] end end