Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make utility for generating git url string #23040

Merged
merged 4 commits into from
Aug 8, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions base/libgit2/callbacks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,15 @@ function authenticate_ssh(creds::SSHCredentials, libgit2credptr::Ptr{Ptr{Void}},
# if username is not provided, then prompt for it
username = if username_ptr == Cstring(C_NULL)
uname = creds.user # check if credentials were already used
!isusedcreds ? uname : prompt("Username for '$schema$host'", default=uname)
prompt_url = git_url(scheme=schema, host=host)
!isusedcreds ? uname : prompt("Username for '$prompt_url'", default=uname)
else
unsafe_string(username_ptr)
end
isempty(username) && return Cint(Error.EAUTH)

prompt_url = git_url(scheme=schema, host=host, username=username)

# For SSH we need a private key location
privatekey = if haskey(ENV,"SSH_KEY_PATH")
ENV["SSH_KEY_PATH"]
Expand All @@ -67,7 +70,7 @@ function authenticate_ssh(creds::SSHCredentials, libgit2credptr::Ptr{Ptr{Void}},
keydefpath = defaultkeydefpath
else
keydefpath =
prompt("Private key location for '$schema$username@$host'", default=keydefpath)
prompt("Private key location for '$prompt_url'", default=keydefpath)
end
end
keydefpath
Expand All @@ -87,7 +90,7 @@ function authenticate_ssh(creds::SSHCredentials, libgit2credptr::Ptr{Ptr{Void}},
keydefpath = privatekey*".pub"
end
if !isfile(keydefpath)
prompt("Public key location for '$schema$username@$host'", default=keydefpath)
prompt("Public key location for '$prompt_url'", default=keydefpath)
end
end
keydefpath
Expand Down Expand Up @@ -144,17 +147,19 @@ function authenticate_userpass(creds::UserPasswordCredentials, libgit2credptr::P
if creds.prompt_if_incorrect
username = creds.user
userpass = creds.pass
prompt_url = git_url(scheme=schema, host=host)
if Sys.iswindows()
if isempty(username) || isempty(userpass) || isusedcreds
res = Base.winprompt("Please enter your credentials for '$schema$host'", "Credentials required",
res = Base.winprompt("Please enter your credentials for '$prompt_url'", "Credentials required",
isempty(username) ? urlusername : username; prompt_username = true)
isnull(res) && return Cint(Error.EAUTH)
username, userpass = Base.get(res)
end
elseif isusedcreds
username = prompt("Username for '$schema$host'",
username = prompt("Username for '$prompt_url'",
default=isempty(username) ? urlusername : username)
userpass = prompt("Password for '$schema$username@$host'", password=true)
prompt_url = git_url(scheme=schema, host=host, username=username)
userpass = prompt("Password for '$prompt_url'", password=true)
end
((creds.user != username) || (creds.pass != userpass)) && reset!(creds)
creds.user = username # save credentials
Expand Down Expand Up @@ -205,7 +210,7 @@ function credentials_callback(libgit2credptr::Ptr{Ptr{Void}}, url_ptr::Cstring,

# parse url for schema and host
urlparts = match(URL_REGEX, url)
schema = urlparts[:scheme] === nothing ? "" : urlparts[:scheme] * "://"
schema = urlparts[:scheme] === nothing ? "" : urlparts[:scheme]
urlusername = urlparts[:user] === nothing ? "" : urlparts[:user]
host = urlparts[:host]

Expand All @@ -224,7 +229,7 @@ function credentials_callback(libgit2credptr::Ptr{Ptr{Void}}, url_ptr::Cstring,

if isset(allowed_types, Cuint(Consts.CREDTYPE_USERPASS_PLAINTEXT))
defaultcreds = reset!(UserPasswordCredentials(true), -1)
credid = "$schema$host"
credid = "$(isempty(schema) ? "ssh" : schema)://$host"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slight change to behaviour here. It used to be that when the schema was not defined in the URL the credential ID would be "$host" now it will be "ssh://$host".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure defaulting to ssh is any better than requiring setting a schema

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that using the scp-like syntax [email protected]:JuliaLang/julia.git or ssh://[email protected]/JuliaLang/julia.git both refer to the same git repo using the SSH protocol.

The advantage of defaulting to using SSH here is that both of these syntaxes will refer to the same credid.

See https://git-scm.com/book/id/v2/Git-on-the-Server-The-Protocols (under "The SSH Protocol" section)

Copy link
Member Author

@omus omus Jul 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could just assign "ssh" to be the schema when one is missing but this would then modify the git_url output from [email protected]:repo.git to ssh://[email protected]/repo.git which would no longer resemble the URL passed in by the user.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what would happen on [email protected]/JuliaLang/julia.git ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based upon the behavour of git clone that URL should be invalid.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right but if it gets passed here will you be prepending ssh to it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently yes. I'll update the URL_REGEX to fix this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL_REGEX no longer allows [email protected]/JuliaLang/julia.git

upcreds = get_creds!(creds, credid, defaultcreds)
# If there were stored SSH credentials, but we ended up here that must
# mean that something went wrong. Replace the SSH credentials by user/pass
Expand Down
38 changes: 38 additions & 0 deletions base/libgit2/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,41 @@ if Sys.iswindows()
else Sys.isunix()
posixpath(path) = path
end

function git_url(;
scheme::AbstractString="",
username::AbstractString="",
password::AbstractString="",
host::AbstractString="",
port::Union{AbstractString,Integer}="",
path::AbstractString="")

port_str = string(port)
scp_syntax = isempty(scheme)

isempty(host) && throw(ArgumentError("A host needs to be specified"))
scp_syntax && !isempty(port_str) && throw(ArgumentError("Port cannot be specified when using scp-like syntax"))

io = IOBuffer()
!isempty(scheme) && print(io, scheme, "://")

if !isempty(username) || !isempty(password)
print(io, username)
!isempty(password) && print(io, ':', password)
print(io, '@')
end

print(io, host)
!isempty(port_str) && print(io, ':', port_str)

if !isempty(path)
if scp_syntax
print(io, ':')
elseif !startswith(path, '/')
print(io, '/')
end
print(io, path)
end

return String(take!(io))
end
88 changes: 88 additions & 0 deletions test/libgit2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,94 @@ end
end
end

@testset "Git URL formatting" begin
@testset "HTTPS URL" begin
url = LibGit2.git_url(
scheme="https",
username="user",
password="pass",
host="server.com",
port=80,
path="/org/project.git")
@test url == "https://user:[email protected]:80/org/project.git"
end

@testset "SSH URL" begin
url = LibGit2.git_url(
scheme="ssh",
username="user",
password="pass",
host="server",
port="22",
path="/project.git")
@test url == "ssh://user:pass@server:22/project.git"
end

@testset "SSH URL, scp-like syntax" begin
url = LibGit2.git_url(
scheme="",
username="user",
host="server",
path="project.git")
@test url == "user@server:project.git"
end

@testset "HTTPS URL, realistic" begin
url = LibGit2.git_url(
scheme="https",
host="github.com",
path="/JuliaLang/Example.jl.git")
@test url == "https://github.com/JuliaLang/Example.jl.git"
end

@testset "SSH URL, realistic" begin
url = LibGit2.git_url(
username="git",
host="github.com",
path="JuliaLang/Example.jl.git")
@test url == "[email protected]:JuliaLang/Example.jl.git"
end

@testset "HTTPS URL, no path" begin
url = LibGit2.git_url(
scheme="https",
username="user",
password="pass",
host="server.com",
port="80")
@test url == "https://user:[email protected]:80"
end

@testset "scp-like syntax, no path" begin
url = LibGit2.git_url(
username="user",
host="server.com")
@test url == "[email protected]"
end

@testset "HTTP URL, path missing slash prefix" begin
url = LibGit2.git_url(
scheme="http",
host="server.com",
path="path")
@test url == "http://server.com/path"
end

@testset "empty" begin
@test_throws ArgumentError LibGit2.git_url()

@test LibGit2.git_url(host="server.com") == "server.com"
url = LibGit2.git_url(
scheme="",
username="",
password="",
host="server.com",
port="",
path="")
@test url == "server.com"
end
end

mktempdir() do dir
# test parameters
repo_url = "https://github.com/JuliaLang/Example.jl"
Expand Down