Catch missing user exception in interactive mode and prompt for it (#180)

This commit is contained in:
Chris de Graaf 2020-06-04 10:09:20 -05:00 committed by GitHub
parent 6db8ffdefc
commit 1c8030be89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 10 deletions

View File

@ -1,7 +1,7 @@
name = "PkgTemplates"
uuid = "14b8a8f1-9102-5b29-a752-f990bacb7fe1"
authors = ["Chris de Graaf", "Invenia Technical Computing Corporation"]
version = "0.7.2"
version = "0.7.3"
[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"

View File

@ -19,6 +19,12 @@ function default_authors()
return "$authors and contributors"
end
struct MissingUserException{T} <: Exception end
function Base.showerror(io::IO, ::MissingUserException{T}) where T
s = """$(nameof(T)): Git hosting service username is required, set one with keyword `user="<username>"`"""
print(io, s)
end
"""
Template(; kwargs...)
@ -95,11 +101,7 @@ function Template(::Val{false}; kwargs...)
if isempty(user)
foreach(plugins) do p
if needs_username(p)
T = nameof(typeof(p))
s = """$T: Git hosting service username is required, set one with keyword `user="<username>"`"""
throw(ArgumentError(s))
end
needs_username(p) && throw(MissingUserException{typeof(p)}())
end
end
@ -184,7 +186,7 @@ function interactive(::Type{Template}; kwargs...)
just_one = length(customizable) == 1
just_one && push(customizable, "None")
return try
try
println("Template keywords to customize:")
menu = MultiSelectMenu(map(string, customizable); pagesize=length(customizable))
customize = customizable[sort!(collect(request(menu)))]
@ -195,17 +197,34 @@ function interactive(::Type{Template}; kwargs...)
kwargs[k] = prompt(Template, fieldtype(Template, k), k)
end
Template(; kwargs...)
while true
try
return Template(; kwargs...)
catch e
e isa MissingUserException || rethrow()
kwargs[:user] = prompt(Template, String, :user)
end
end
catch e
e isa InterruptException || rethrow()
println()
@info "Cancelled"
nothing
return nothing
end
end
prompt(::Type{Template}, ::Type, ::Val{:pkg}) = Base.prompt("Package name")
function prompt(::Type{Template}, ::Type, ::Val{:user})
return if isempty(default_user())
input = Base.prompt("Enter value for 'user' (String, required)")
input === nothing && throw(InterruptException())
return input
else
fallback_prompt(String, :user)
end
end
function prompt(::Type{Template}, ::Type, ::Val{:host})
hosts = ["github.com", "gitlab.com", "bitbucket.org", "Other"]
menu = RadioMenu(hosts; pagesize=length(hosts))

View File

@ -9,6 +9,7 @@ const DOWN = "\eOB"
const ALL = "a"
const NONE = "n"
const DONE = "d"
const SIGINT = "\x03"
# Because the plugin selection dialog prints directly to stdin in the same way
# as we do here, and our input prints happen first, we're going to need to insert
@ -206,6 +207,25 @@ end
@test PT.interactive(Codecov) == Codecov()
end
@testset "Missing user" begin
print(
stdin.buffer,
DONE, # Customize nothing
"username", LF, # Enter user after it's prompted
)
mock(PT.default_user => () -> "") do _du
@test Template(; interactive=true) == Template(; user="username")
end
end
@testset "Interrupts" begin
print(
stdin.buffer,
SIGINT, # Send keyboard interrupt
)
@test Template(; interactive=true) === nothing
end
println()
end
end

View File

@ -3,8 +3,10 @@
@testset "Template" begin
@testset "Template constructor" begin
@testset "user" begin
msg = sprint(showerror, PT.MissingUserException{TravisCI}())
@test startswith(msg, "TravisCI: ")
mock(PT.default_user => () -> "") do _du
@test_throws ArgumentError Template()
@test_throws PT.MissingUserException Template()
@test isempty(Template(; plugins=[!Git]).user)
end
mock(PT.default_user => () -> "username") do _du