diff --git a/src/API.jl b/src/API.jl index a3ae6e8fcf..86f75266a7 100644 --- a/src/API.jl +++ b/src/API.jl @@ -544,7 +544,15 @@ function activate(path::AbstractString; shared::Bool=false) Base.ACTIVE_PROJECT[] = Base.load_path_expand(fullpath) end -setprotocol!(proto::Union{Nothing, AbstractString}=nothing) = GitTools.setprotocol!(proto) +function setprotocol!(; + domain::AbstractString="github.com", + protocol::Union{Nothing, AbstractString}=nothing +) + GitTools.setprotocol!(domain=domain, protocol=protocol) + return nothing +end + +@deprecate setprotocol!(proto::Union{Nothing, AbstractString}) setprotocol!(protocol = proto) false # API constructor function Package(;name::Union{Nothing,AbstractString} = nothing, diff --git a/src/GitTools.jl b/src/GitTools.jl index cd5116dce8..a6fdbede30 100644 --- a/src/GitTools.jl +++ b/src/GitTools.jl @@ -65,22 +65,39 @@ function transfer_progress(progress::Ptr{LibGit2.TransferProgress}, p::Any) return Cint(0) end +const GIT_REGEX = + r"^(?:(?git|ssh|https)://)?(?:[\w\.\+\-:]+@)?(?.+?)(?()/|:)(?.+?)(?:\.git)?$" +const GIT_PROTOCOLS = Dict{String, Union{Nothing, String}}() +const GIT_USERS = Dict{String, Union{Nothing, String}}() -const GITHUB_REGEX = - r"^(?:git@|git://|https://(?:[\w\.\+\-]+@)?)github.com[:/](([^/].+)/(.+?))(?:\.git)?$"i -const GIT_PROTOCOL = Ref{Union{String, Nothing}}(nothing) +@deprecate setprotocol!(proto::Union{Nothing, AbstractString}) setprotocol!(protocol = proto) false -setprotocol!(proto::Union{Nothing, AbstractString}=nothing) = GIT_PROTOCOL[] = proto +function setprotocol!(; + domain::AbstractString="github.com", + protocol::Union{Nothing, AbstractString}=nothing, + user::Union{Nothing, AbstractString}=(protocol == "ssh" ? "git" : nothing) +) + domain = lowercase(domain) + GIT_PROTOCOLS[domain] = protocol + GIT_USERS[domain] = user +end -# TODO: extend this to more urls function normalize_url(url::AbstractString) - m = match(GITHUB_REGEX, url) - if m === nothing || GIT_PROTOCOL[] === nothing + m = match(GIT_REGEX, url) + m === nothing && return url + + host = m[:hostname] + path = "$(m[:path]).git" + + proto = get(GIT_PROTOCOLS, lowercase(host), nothing) + + if proto === nothing url - elseif GIT_PROTOCOL[] == "ssh" - "ssh://git@github.com/$(m.captures[1]).git" else - "$(GIT_PROTOCOL[])://github.com/$(m.captures[1]).git" + user = get(GIT_USERS, lowercase(host), nothing) + user = user === nothing ? "" : "$user@" + + "$proto://$user$host/$path" end end diff --git a/src/Pkg.jl b/src/Pkg.jl index e5a3fdcd22..568e3dd9d1 100644 --- a/src/Pkg.jl +++ b/src/Pkg.jl @@ -337,11 +337,21 @@ Below is a comparison between the REPL version and the `PackageSpec` version: const PackageSpec = API.Package """ - Pkg.setprotocol!(proto::Union{Nothing, AbstractString}=nothing) + setprotocol!(; + domain::AbstractString = "github.com", + protocol::Union{Nothing, AbstractString}=nothing + ) -Set the protocol used to access GitHub-hosted packages when `add`ing a url or `develop`ing a package. +Set the protocol used to access hosted packages when `add`ing a url or `develop`ing a package. Defaults to delegating the choice to the package developer (`proto == nothing`). Other choices for `proto` are `"https"` or `"git"`. + +# Examples +```julia-repl +julia> Pkg.setprotocol!(domain = "github.com", protocol = "ssh") + +julia> Pkg.setprotocol!(domain = "gitlab.mycompany.com") +``` """ const setprotocol! = API.setprotocol! diff --git a/test/pkg.jl b/test/pkg.jl index c0c5ffd827..e4c89d5b0e 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -254,13 +254,13 @@ temp_pkg_dir() do project_path mktempdir() do devdir withenv("JULIA_PKG_DEVDIR" => devdir) do try - Pkg.setprotocol!("notarealprotocol") + Pkg.setprotocol!(domain = "github.com", protocol = "notarealprotocol") @test_throws PkgError Pkg.develop("Example") - Pkg.setprotocol!("https") + Pkg.setprotocol!(domain = "github.com", protocol = "https") Pkg.develop("Example") @test isinstalled(TEST_PKG) finally - Pkg.setprotocol!() + Pkg.setprotocol!(domain = "github.com") end end end @@ -270,14 +270,26 @@ temp_pkg_dir() do project_path https_url = "https://github.com/JuliaLang/Example.jl.git" ssh_url = "ssh://git@github.com/JuliaLang/Example.jl.git" @test Pkg.GitTools.normalize_url(https_url) == https_url - Pkg.setprotocol!("ssh") + Pkg.setprotocol!(domain = "github.com", protocol = "ssh") @test Pkg.GitTools.normalize_url(https_url) == ssh_url # TODO: figure out how to test this without # having to deploy a ssh key on github #Pkg.develop("Example") #@test isinstalled(TEST_PKG) + + https_url = "https://gitlab.example.com/example/Example.jl.git" + ssh_url = "ssh://git@gitlab.example.com/example/Example.jl.git" + + @test Pkg.GitTools.normalize_url(https_url) == https_url + Pkg.setprotocol!(domain = "gitlab.example.com", protocol = "ssh") + @test Pkg.GitTools.normalize_url(https_url) == ssh_url + + @test_deprecated Pkg.setprotocol!("ssh") + @test_deprecated Pkg.GitTools.setprotocol!("ssh") + finally - Pkg.setprotocol!() + Pkg.setprotocol!(domain = "github.com") + Pkg.setprotocol!(domain = "gitlab.example.com") end end end