Add execution priority to plugins
This commit is contained in:
parent
980452fde3
commit
0cf6d47ada
@ -19,9 +19,8 @@ However, it's probably desirable to customize the template to your liking with v
|
|||||||
```jl
|
```jl
|
||||||
t = Template(;
|
t = Template(;
|
||||||
dir="~/code",
|
dir="~/code",
|
||||||
ssh=true,
|
|
||||||
manifest=true,
|
|
||||||
plugins=[
|
plugins=[
|
||||||
|
Git(; manifest=true, ssh=true),
|
||||||
Codecov(),
|
Codecov(),
|
||||||
TravisCI(; x86=true),
|
TravisCI(; x86=true),
|
||||||
Documenter{TravisCI}(),
|
Documenter{TravisCI}(),
|
||||||
|
@ -94,6 +94,7 @@ view
|
|||||||
Finally, we implement [`hook`](@ref), which is the real workhorse for the plugin.
|
Finally, we implement [`hook`](@ref), which is the real workhorse for the plugin.
|
||||||
|
|
||||||
TODO prehook and posthook in examples
|
TODO prehook and posthook in examples
|
||||||
|
TODO priority
|
||||||
|
|
||||||
```@docs
|
```@docs
|
||||||
prehook
|
prehook
|
||||||
|
@ -5,8 +5,10 @@
|
|||||||
|
|
||||||
function Base.show(io::IO, ::MIME"text/plain", p::T) where T <: Plugin
|
function Base.show(io::IO, ::MIME"text/plain", p::T) where T <: Plugin
|
||||||
indent = get(io, :indent, 0)
|
indent = get(io, :indent, 0)
|
||||||
print(io, repeat(' ', indent), T, ":")
|
print(io, repeat(' ', indent), T)
|
||||||
foreach(fieldnames(T)) do n
|
ns = fieldnames(T)
|
||||||
|
isempty(ns) || print(io, ":")
|
||||||
|
foreach(ns) do n
|
||||||
println(io)
|
println(io)
|
||||||
print(io, repeat(' ', indent + 2), n, ": ", show_field(getfield(p, n)))
|
print(io, repeat(' ', indent + 2), n, ": ", show_field(getfield(p, n)))
|
||||||
end
|
end
|
||||||
@ -28,7 +30,7 @@ function Base.show(io::IO, m::MIME"text/plain", t::Template)
|
|||||||
print(io, " plugins: None")
|
print(io, " plugins: None")
|
||||||
else
|
else
|
||||||
print(io, repeat(' ', 2), "plugins:")
|
print(io, repeat(' ', 2), "plugins:")
|
||||||
foreach(sort(collect(values(t.plugins)); by=string)) do p
|
foreach(sort(t.plugins; by=string)) do p
|
||||||
println(io)
|
println(io)
|
||||||
show(IOContext(io, :indent => 4), m, p)
|
show(IOContext(io, :indent => 4), m, p)
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
const TEMPLATES_DIR = normpath(joinpath(@__DIR__, "..", "templates"))
|
const TEMPLATES_DIR = normpath(joinpath(@__DIR__, "..", "templates"))
|
||||||
|
const DEFAULT_PRIORITY = 1000
|
||||||
|
|
||||||
"""
|
"""
|
||||||
A simple plugin that, in general, creates a single file.
|
A simple plugin that, in general, creates a single file.
|
||||||
@ -59,6 +60,14 @@ By default, the tags are `"{{"` and `"}}"`.
|
|||||||
"""
|
"""
|
||||||
tags(::Plugin) = "{{", "}}"
|
tags(::Plugin) = "{{", "}}"
|
||||||
|
|
||||||
|
"""
|
||||||
|
priority(::Plugin) -> Int
|
||||||
|
|
||||||
|
Determines the order in which plugins are processed (higher goes first).
|
||||||
|
The default priority (`DEFAULT_PRIORITY`), is `$DEFAULT_PRIORITY`.
|
||||||
|
"""
|
||||||
|
priority(::Plugin) = DEFAULT_PRIORITY
|
||||||
|
|
||||||
"""
|
"""
|
||||||
gitignore(::Plugin) -> Vector{String}
|
gitignore(::Plugin) -> Vector{String}
|
||||||
|
|
||||||
@ -131,7 +140,7 @@ At this point, `pkg_dir` is an empty directory that will eventually contain the
|
|||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
`pkg_dir` only stays empty until the first plugin chooses to create a file.
|
`pkg_dir` only stays empty until the first plugin chooses to create a file.
|
||||||
Don't count on the order in which the plugins are sorted!
|
See also: [`priority`](@ref).
|
||||||
"""
|
"""
|
||||||
prehook(::Plugin, ::Template, ::AbstractString) = nothing
|
prehook(::Plugin, ::Template, ::AbstractString) = nothing
|
||||||
|
|
||||||
|
@ -254,10 +254,10 @@ end
|
|||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
is_ci(::Type{T}) -> Bool
|
is_ci(::Plugin) -> Bool
|
||||||
|
|
||||||
Determine whether or not `T` is a CI plugin.
|
Determine whether or not a plugin is a CI plugin.
|
||||||
If you are adding a CI plugin, you should implement this function and return `true`.
|
If you are adding a CI plugin, you should implement this function and return `true`.
|
||||||
"""
|
"""
|
||||||
is_ci(::Type) = false
|
is_ci(::Plugin) = false
|
||||||
is_ci(::Type{<:Union{AppVeyor, TravisCI, CirrusCI, GitLabCI}}) = true
|
is_ci(::Union{AppVeyor, TravisCI, CirrusCI, GitLabCI}) = true
|
||||||
|
@ -45,10 +45,10 @@ badges(::Coveralls) = Badge(
|
|||||||
gitignore(::Union{Codecov, Coveralls}) = COVERAGE_GITIGNORE
|
gitignore(::Union{Codecov, Coveralls}) = COVERAGE_GITIGNORE
|
||||||
|
|
||||||
"""
|
"""
|
||||||
is_coverage(::Type{T}) -> Bool
|
is_coverage(::Plugin) -> Bool
|
||||||
|
|
||||||
Determine whether or not `T` is a coverage plugin.
|
Determine whether or not a plugin is a coverage plugin.
|
||||||
If you are adding a coverage plugin, you should implement this function and return `true`.
|
If you are adding a coverage plugin, you should implement this function and return `true`.
|
||||||
"""
|
"""
|
||||||
is_coverage(::Type) = false
|
is_coverage(::Plugin) = false
|
||||||
is_coverage(::Type{<:Union{Codecov, Coveralls}}) = true
|
is_coverage(::Union{Codecov, Coveralls}) = true
|
||||||
|
@ -50,7 +50,7 @@ end
|
|||||||
|
|
||||||
# Create the .gitignore.
|
# Create the .gitignore.
|
||||||
function hook(p::Git, t::Template, pkg_dir::AbstractString)
|
function hook(p::Git, t::Template, pkg_dir::AbstractString)
|
||||||
ignore = mapreduce(gitignore, append!, values(t.plugins))
|
ignore = mapreduce(gitignore, append!, t.plugins)
|
||||||
# Only ignore manifests at the repo root.
|
# Only ignore manifests at the repo root.
|
||||||
p.manifest || "Manifest.toml" in ignore || push!(ignore, "/Manifest.toml")
|
p.manifest || "Manifest.toml" in ignore || push!(ignore, "/Manifest.toml")
|
||||||
unique!(sort!(ignore))
|
unique!(sort!(ignore))
|
||||||
|
@ -5,8 +5,10 @@ Creates a `Project.toml`.
|
|||||||
"""
|
"""
|
||||||
struct ProjectFile <: Plugin end
|
struct ProjectFile <: Plugin end
|
||||||
|
|
||||||
# Create Project.toml in the prehook because other hooks might depend on it.
|
# Other plugins like Tests will modify this file.
|
||||||
function prehook(::ProjectFile, t::Template, pkg_dir::AbstractString)
|
priority(::ProjectFile) = typemax(Int) - DEFAULT_PRIORITY + 1
|
||||||
|
|
||||||
|
function hook(::ProjectFile, t::Template, pkg_dir::AbstractString)
|
||||||
toml = Dict(
|
toml = Dict(
|
||||||
"name" => basename(pkg_dir),
|
"name" => basename(pkg_dir),
|
||||||
"uuid" => uuid4(),
|
"uuid" => uuid4(),
|
||||||
|
@ -29,19 +29,18 @@ function view(p::Readme, t::Template, pkg::AbstractString)
|
|||||||
done = DataType[]
|
done = DataType[]
|
||||||
foreach(badge_order()) do T
|
foreach(badge_order()) do T
|
||||||
if hasplugin(t, T)
|
if hasplugin(t, T)
|
||||||
bs = badges(t.plugins[T], t, pkg)
|
append!(strings, badges(getplugin(t, T), t, pkg))
|
||||||
append!(strings, badges(t.plugins[T], t, pkg))
|
|
||||||
push!(done, T)
|
push!(done, T)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
foreach(setdiff(keys(t.plugins), done)) do T
|
# And the rest go after, in no particular order.
|
||||||
bs = badges(t.plugins[T], t, pkg)
|
foreach(setdiff(map(typeof, t.plugins), done)) do T
|
||||||
append!(strings, badges(t.plugins[T], t, pkg))
|
append!(strings, badges(getplugin(t, T), t, pkg))
|
||||||
end
|
end
|
||||||
|
|
||||||
return Dict(
|
return Dict(
|
||||||
"BADGES" => strings,
|
"BADGES" => strings,
|
||||||
"HAS_CITATION" => hasplugin(t, Citation) && t.plugins[Citation].readme,
|
"HAS_CITATION" => hasplugin(t, Citation) && getplugin(t, Citation).readme,
|
||||||
"HAS_INLINE_BADGES" => !isempty(strings) && p.inline_badges,
|
"HAS_INLINE_BADGES" => !isempty(strings) && p.inline_badges,
|
||||||
"PKG" => pkg,
|
"PKG" => pkg,
|
||||||
)
|
)
|
||||||
|
@ -54,7 +54,7 @@ struct Template
|
|||||||
dir::String
|
dir::String
|
||||||
host::String
|
host::String
|
||||||
julia_version::VersionNumber
|
julia_version::VersionNumber
|
||||||
plugins::Dict{DataType, <:Plugin}
|
plugins::Vector{<:Plugin}
|
||||||
user::String
|
user::String
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -72,33 +72,17 @@ function Template(::Val{false}; kwargs...)
|
|||||||
host = replace(getkw(kwargs, :host), r".*://" => "")
|
host = replace(getkw(kwargs, :host), r".*://" => "")
|
||||||
julia_version = getkw(kwargs, :julia_version)
|
julia_version = getkw(kwargs, :julia_version)
|
||||||
|
|
||||||
|
# User-supplied plugins come first, so that deduping the list will remove the defaults.
|
||||||
|
plugins = Plugin[]
|
||||||
|
append!(plugins, getkw(kwargs, :plugins))
|
||||||
disabled = getkw(kwargs, :disable_defaults)
|
disabled = getkw(kwargs, :disable_defaults)
|
||||||
enabled = filter(p -> !(typeof(p) in disabled), default_plugins())
|
append!(plugins, filter(p -> !(typeof(p) in disabled), default_plugins()))
|
||||||
append!(enabled, getkw(kwargs, :plugins))
|
plugins = unique(typeof, plugins)
|
||||||
# This comprehension resolves duplicate plugin types by overwriting,
|
sort!(plugins; by=priority, rev=true)
|
||||||
# which means that default plugins get replaced by user values.
|
|
||||||
plugins = Dict(typeof(p) => p for p in enabled)
|
|
||||||
|
|
||||||
return Template(authors, dir, host, julia_version, plugins, user)
|
return Template(authors, dir, host, julia_version, plugins, user)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Does the template have a plugin that satisfies some predicate?
|
|
||||||
hasplugin(t::Template, f::Function) = any(f, keys(t.plugins))
|
|
||||||
hasplugin(t::Template, ::Type{T}) where T <: Plugin = hasplugin(t, U -> U <: T)
|
|
||||||
|
|
||||||
# Get a keyword, or compute some default value.
|
|
||||||
getkw(kwargs, k) = get(() -> defaultkw(k), kwargs, k)
|
|
||||||
|
|
||||||
# Default Template keyword values.
|
|
||||||
defaultkw(s::Symbol) = defaultkw(Val(s))
|
|
||||||
defaultkw(::Val{:authors}) = default_authors()
|
|
||||||
defaultkw(::Val{:dir}) = Pkg.devdir()
|
|
||||||
defaultkw(::Val{:disable_defaults}) = DataType[]
|
|
||||||
defaultkw(::Val{:host}) = "github.com"
|
|
||||||
defaultkw(::Val{:julia_version}) = default_version()
|
|
||||||
defaultkw(::Val{:plugins}) = Plugin[]
|
|
||||||
defaultkw(::Val{:user}) = default_user()
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
(::Template)(pkg::AbstractString)
|
(::Template)(pkg::AbstractString)
|
||||||
|
|
||||||
@ -113,7 +97,7 @@ function (t::Template)(pkg::AbstractString)
|
|||||||
try
|
try
|
||||||
foreach((prehook, hook, posthook)) do h
|
foreach((prehook, hook, posthook)) do h
|
||||||
@info "Running $(h)s"
|
@info "Running $(h)s"
|
||||||
foreach(values(t.plugins)) do p
|
foreach(t.plugins) do p
|
||||||
h(p, t, pkg_dir)
|
h(p, t, pkg_dir)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -124,3 +108,26 @@ function (t::Template)(pkg::AbstractString)
|
|||||||
|
|
||||||
@info "New package is at $pkg_dir"
|
@info "New package is at $pkg_dir"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Does the template have a plugin that satisfies some predicate?
|
||||||
|
hasplugin(t::Template, f::Function) = any(f, t.plugins)
|
||||||
|
hasplugin(t::Template, ::Type{T}) where T <: Plugin = hasplugin(t, p -> p isa T)
|
||||||
|
|
||||||
|
# Get a plugin by type.
|
||||||
|
function getplugin(t::Template, ::Type{T}) where T <: Plugin
|
||||||
|
i = findfirst(p -> p isa T, t.plugins)
|
||||||
|
i === nothing ? nothing : t.plugins[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get a keyword, or compute some default value.
|
||||||
|
getkw(kwargs, k) = get(() -> defaultkw(k), kwargs, k)
|
||||||
|
|
||||||
|
# Default Template keyword values.
|
||||||
|
defaultkw(s::Symbol) = defaultkw(Val(s))
|
||||||
|
defaultkw(::Val{:authors}) = default_authors()
|
||||||
|
defaultkw(::Val{:dir}) = Pkg.devdir()
|
||||||
|
defaultkw(::Val{:disable_defaults}) = DataType[]
|
||||||
|
defaultkw(::Val{:host}) = "github.com"
|
||||||
|
defaultkw(::Val{:julia_version}) = default_version()
|
||||||
|
defaultkw(::Val{:plugins}) = Plugin[]
|
||||||
|
defaultkw(::Val{:user}) = default_user()
|
||||||
|
@ -39,7 +39,7 @@ const LICENSES_DIR = joinpath(TEMPLATES_DIR, "licenses")
|
|||||||
License:
|
License:
|
||||||
path: "$(joinpath(LICENSES_DIR, "MIT"))"
|
path: "$(joinpath(LICENSES_DIR, "MIT"))"
|
||||||
destination: "LICENSE"
|
destination: "LICENSE"
|
||||||
ProjectFile:
|
ProjectFile
|
||||||
Readme:
|
Readme:
|
||||||
file: "$(joinpath(TEMPLATES_DIR, "README.md"))"
|
file: "$(joinpath(TEMPLATES_DIR, "README.md"))"
|
||||||
destination: "README.md"
|
destination: "README.md"
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
@testset "plugins / disabled_defaults" begin
|
@testset "plugins / disabled_defaults" begin
|
||||||
function test_plugins(plugins, expected, disabled=DataType[])
|
function test_plugins(plugins, expected, disabled=DataType[])
|
||||||
t = tpl(; plugins=plugins, disable_defaults=disabled)
|
t = tpl(; plugins=plugins, disable_defaults=disabled)
|
||||||
@test issetequal(values(t.plugins), expected)
|
@test issetequal(t.plugins, expected)
|
||||||
end
|
end
|
||||||
|
|
||||||
defaults = PT.default_plugins()
|
defaults = PT.default_plugins()
|
||||||
|
Loading…
Reference in New Issue
Block a user