Move the default plugins into their own files, fix some bugs
This commit is contained in:
parent
146c1bdbe5
commit
2a5fb5ccc8
@ -1,4 +1,4 @@
|
||||
const DEFAULTS_DIR = normpath(joinpath(@__DIR__, "..", "templates"))
|
||||
const TEMPLATES_DIR = normpath(joinpath(@__DIR__, "..", "templates"))
|
||||
|
||||
"""
|
||||
A simple plugin that, in general, creates a single file.
|
||||
@ -8,9 +8,9 @@ abstract type BasicPlugin <: Plugin end
|
||||
"""
|
||||
default_file(paths::AbstractString...) -> String
|
||||
|
||||
Return a path relative to the default template file directory (`$(contractuser(DEFAULTS_DIR))`).
|
||||
Return a path relative to the default template file directory (`$(contractuser(TEMPLATES_DIR))`).
|
||||
"""
|
||||
default_file(paths::AbstractString...) = joinpath(DEFAULTS_DIR, paths...)
|
||||
default_file(paths::AbstractString...) = joinpath(TEMPLATES_DIR, paths...)
|
||||
|
||||
"""
|
||||
view(::Plugin, ::Template, pkg::AbstractString) -> Dict{String, Any}
|
||||
@ -205,9 +205,14 @@ function render_text(text::AbstractString, view::Dict{<:AbstractString}, tags=no
|
||||
return tags === nothing ? render(text, view) : render(text, view; tags=tags)
|
||||
end
|
||||
|
||||
include(joinpath("plugins", "defaults.jl"))
|
||||
include(joinpath("plugins", "project_file.jl"))
|
||||
include(joinpath("plugins", "src_dir.jl"))
|
||||
include(joinpath("plugins", "tests.jl"))
|
||||
include(joinpath("plugins", "readme.jl"))
|
||||
include(joinpath("plugins", "license.jl"))
|
||||
include(joinpath("plugins", "git.jl"))
|
||||
include(joinpath("plugins", "develop.jl"))
|
||||
include(joinpath("plugins", "coverage.jl"))
|
||||
include(joinpath("plugins", "ci.jl"))
|
||||
include(joinpath("plugins", "citation.jl"))
|
||||
include(joinpath("plugins", "develop.jl"))
|
||||
include(joinpath("plugins", "documenter.jl"))
|
||||
|
@ -1,306 +0,0 @@
|
||||
const TEST_UUID = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
const TEST_DEP = PackageSpec(; name="Test", uuid=TEST_UUID)
|
||||
|
||||
badge_order() = [
|
||||
Documenter{GitLabCI},
|
||||
Documenter{TravisCI},
|
||||
GitLabCI,
|
||||
TravisCI,
|
||||
AppVeyor,
|
||||
CirrusCI,
|
||||
Codecov,
|
||||
Coveralls,
|
||||
]
|
||||
|
||||
"""
|
||||
ProjectFile()
|
||||
|
||||
Creates a `Project.toml`.
|
||||
"""
|
||||
struct ProjectFile <: Plugin end
|
||||
|
||||
# Create Project.toml in the prehook because other hooks might depend on it.
|
||||
function prehook(::ProjectFile, t::Template, pkg_dir::AbstractString)
|
||||
toml = Dict(
|
||||
"name" => basename(pkg_dir),
|
||||
"uuid" => uuid4(),
|
||||
"authors" => t.authors,
|
||||
"compat" => Dict("julia" => compat_version(t.julia_version)),
|
||||
)
|
||||
open(io -> TOML.print(io, toml), joinpath(pkg_dir, "Project.toml"), "w")
|
||||
end
|
||||
|
||||
"""
|
||||
compat_version(v::VersionNumber) -> String
|
||||
|
||||
Format a `VersionNumber` to exclude trailing zero components.
|
||||
"""
|
||||
function compat_version(v::VersionNumber)
|
||||
return if v.patch == 0 && v.minor == 0
|
||||
"$(v.major)"
|
||||
elseif v.patch == 0
|
||||
"$(v.major).$(v.minor)"
|
||||
else
|
||||
"$(v.major).$(v.minor).$(v.patch)"
|
||||
end
|
||||
end
|
||||
|
||||
"""
|
||||
SrcDir(; file="$(contractuser(default_file("src", "module.jl")))")
|
||||
|
||||
Creates a module entrypoint.
|
||||
"""
|
||||
@with_kw_noshow mutable struct SrcDir <: BasicPlugin
|
||||
file::String = default_file("src", "module.jl")
|
||||
destination::String = joinpath("src", "<module>.jl")
|
||||
end
|
||||
|
||||
# Don't display the destination field.
|
||||
function Base.show(io::IO, ::MIME"text/plain", p::SrcDir)
|
||||
indent = get(io, :indent, 0)
|
||||
print(io, repeat(' ', indent), "SrcDir:")
|
||||
print(io, "\n", repeat(' ', indent + 2), "file: ", show_field(p.file))
|
||||
end
|
||||
|
||||
source(p::SrcDir) = p.file
|
||||
destination(p::SrcDir) = p.destination
|
||||
view(::SrcDir, ::Template, pkg::AbstractString) = Dict("PKG" => pkg)
|
||||
|
||||
# Update the destination now that we know the package name.
|
||||
# Kind of hacky, but oh well.
|
||||
function prehook(p::SrcDir, t::Template, pkg_dir::AbstractString)
|
||||
invoke(prehook, Tuple{BasicPlugin, Template, AbstractString}, p, t, pkg_dir)
|
||||
p.destination = joinpath("src", basename(pkg_dir) * ".jl")
|
||||
end
|
||||
|
||||
"""
|
||||
Readme(;
|
||||
file="$(contractuser(default_file("README.md")))",
|
||||
destination="README.md",
|
||||
inline_badges=false,
|
||||
)
|
||||
|
||||
Creates a `README` file.
|
||||
By default, it includes badges for other included plugins
|
||||
|
||||
## Keyword Arguments
|
||||
- `file::AbstractString`: Template file for the `README`.
|
||||
- `destination::AbstractString`: File destination, relative to the repository root.
|
||||
For example, values of `"README"` or `"README.rst"` might be desired.
|
||||
- `inline_badges::Bool`: Whether or not to put the badges on the same line as the package name.
|
||||
"""
|
||||
@with_kw_noshow struct Readme <: BasicPlugin
|
||||
file::String = default_file("README.md")
|
||||
destination::String = "README.md"
|
||||
inline_badges::Bool = false
|
||||
end
|
||||
|
||||
source(p::Readme) = p.file
|
||||
destination(p::Readme) = p.destination
|
||||
|
||||
function view(p::Readme, t::Template, pkg::AbstractString)
|
||||
# Explicitly ordered badges go first.
|
||||
strings = String[]
|
||||
done = DataType[]
|
||||
foreach(badge_order()) do T
|
||||
if hasplugin(t, T)
|
||||
bs = badges(t.plugins[T], t, pkg)
|
||||
append!(strings, badges(t.plugins[T], t, pkg))
|
||||
push!(done, T)
|
||||
end
|
||||
end
|
||||
foreach(setdiff(keys(t.plugins), done)) do T
|
||||
bs = badges(t.plugins[T], t, pkg)
|
||||
append!(strings, badges(t.plugins[T], t, pkg))
|
||||
end
|
||||
|
||||
return Dict(
|
||||
"BADGES" => strings,
|
||||
"HAS_CITATION" => hasplugin(t, Citation) && t.plugins[Citation].readme,
|
||||
"HAS_INLINE_BADGES" => !isempty(strings) && p.inline_badges,
|
||||
"PKG" => pkg,
|
||||
)
|
||||
end
|
||||
|
||||
"""
|
||||
License(; name="MIT", path=nothing, destination="LICENSE")
|
||||
|
||||
Creates a license file.
|
||||
|
||||
## Keyword Arguments
|
||||
- `name::AbstractString`: Name of a license supported by PkgTemplates.
|
||||
Available licenses can be seen [here](https://github.com/invenia/PkgTemplates.jl/tree/master/templates/licenses).
|
||||
- `path::Union{AbstractString, Nothing}`: Path to a custom license file.
|
||||
This keyword takes priority over `name`.
|
||||
- `destination::AbstractString`: File destination, relative to the repository root.
|
||||
For example, `"LICENSE.md"` might be desired.
|
||||
"""
|
||||
struct License <: BasicPlugin
|
||||
path::String
|
||||
destination::String
|
||||
end
|
||||
|
||||
function License(
|
||||
name::AbstractString="MIT",
|
||||
path::Union{AbstractString, Nothing}=nothing,
|
||||
destination::AbstractString="LICENSE",
|
||||
)
|
||||
if path === nothing
|
||||
path = default_file("licenses", name)
|
||||
isfile(path) || throw(ArgumentError("License '$(basename(path))' is not available"))
|
||||
end
|
||||
return License(path, destination)
|
||||
end
|
||||
|
||||
|
||||
source(p::License) = p.path
|
||||
destination(p::License) = p.destination
|
||||
view(::License, t::Template, ::AbstractString) = Dict(
|
||||
"AUTHORS" => join(t.authors, ", "),
|
||||
"YEAR" => year(today()),
|
||||
)
|
||||
|
||||
"""
|
||||
Git(; ignore=String[], ssh=false, manifest=false, gpgsign=false)
|
||||
|
||||
Creates a Git repository and a `.gitignore` file.
|
||||
|
||||
## Keyword Arguments
|
||||
- `ignore::Vector{<:AbstractString}`: Patterns to add to the `.gitignore`.
|
||||
See also: [`gitignore`](@ref).
|
||||
- `ssh::Bool`: Whether or not to use SSH for the remote.
|
||||
If left unset, HTTPS is used.
|
||||
- `manifest::Bool`: Whether or not to commit `Manifest.toml`.
|
||||
- `gpgsign::Bool`: Whether or not to sign commits with your GPG key.
|
||||
This option requires that the Git CLI is installed.
|
||||
"""
|
||||
@with_kw_noshow struct Git <: Plugin
|
||||
ignore::Vector{String} = []
|
||||
ssh::Bool = false
|
||||
manifest::Bool = false
|
||||
gpgsign::Bool = false
|
||||
end
|
||||
|
||||
gitignore(p::Git) = p.ignore
|
||||
|
||||
# Set up the Git repository.
|
||||
function prehook(p::Git, t::Template, pkg_dir::AbstractString)
|
||||
if p.gpgsign && try run(pipeline(`git --version`; stdout=devnull)); false catch; true end
|
||||
throw(ArgumentError("Git: gpgsign is set but the Git CLI is not installed"))
|
||||
end
|
||||
LibGit2.with(LibGit2.init(pkg_dir)) do repo
|
||||
commit(p, repo, pkg_dir, "Initial commit")
|
||||
pkg = basename(pkg_dir)
|
||||
url = if p.ssh
|
||||
"git@$(t.host):$(t.user)/$pkg.jl.git"
|
||||
else
|
||||
"https://$(t.host)/$(t.user)/$pkg.jl"
|
||||
end
|
||||
LibGit2.with(GitRemote(repo, "origin", url)) do remote
|
||||
# TODO: `git pull` still requires some Git branch config.
|
||||
LibGit2.add_push!(repo, remote, "refs/heads/master")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Create the .gitignore.
|
||||
function hook(p::Git, t::Template, pkg_dir::AbstractString)
|
||||
gen_file(joinpath(pkg_dir, ".gitignore"), render_plugin(p, t))
|
||||
end
|
||||
|
||||
# Commit the files
|
||||
function posthook(p::Git, t::Template, pkg_dir::AbstractString)
|
||||
# Ensure that the manifest exists if it's going to be committed.
|
||||
manifest = joinpath(pkg_dir, "Manifest.toml")
|
||||
if p.manifest && !isfile(manifest)
|
||||
touch(manifest)
|
||||
with_project(Pkg.update, pkg_dir)
|
||||
end
|
||||
|
||||
LibGit2.with(GitRepo(pkg_dir)) do repo
|
||||
LibGit2.add!(repo, ".")
|
||||
msg = "Files generated by PkgTemplates"
|
||||
installed = Pkg.installed()
|
||||
if haskey(installed, "PkgTemplates")
|
||||
ver = string(installed["PkgTemplates"])
|
||||
msg *= "\n\nPkgTemplates version: $ver"
|
||||
end
|
||||
commit(p, repo, pkg_dir, msg)
|
||||
end
|
||||
end
|
||||
|
||||
function commit(p::Git, repo::GitRepo, pkg_dir::AbstractString, msg::AbstractString)
|
||||
if p.gpgsign
|
||||
run(pipeline(`git -C $pkg_dir commit -S --allow-empty -m $msg`; stdout=devnull))
|
||||
else
|
||||
LibGit2.commit(repo, msg)
|
||||
end
|
||||
end
|
||||
|
||||
function render_plugin(p::Git, t::Template)
|
||||
ignore = mapreduce(gitignore, append!, values(t.plugins))
|
||||
# Only ignore manifests at the repo root.
|
||||
p.manifest || "Manifest.toml" in ignore || push!(ignore, "/Manifest.toml")
|
||||
unique!(sort!(ignore))
|
||||
return join(ignore, "\n")
|
||||
end
|
||||
|
||||
"""
|
||||
Tests(; file="$(contractuser(default_file("test", "runtests.jl")))", project=false)
|
||||
|
||||
Sets up testing for packages.
|
||||
|
||||
## Keyword Arguments
|
||||
- `file::AbstractString`: Template file for the `runtests.jl`.
|
||||
- `project::Bool`: Whether or not to create a new project for tests (`test/Project.toml`).
|
||||
See [here](https://julialang.github.io/Pkg.jl/v1/creating-packages/#Test-specific-dependencies-in-Julia-1.2-and-above-1) for more details.
|
||||
|
||||
!!! note
|
||||
Managing test dependencies with `test/Project.toml` is only supported in Julia 1.2 and later.
|
||||
"""
|
||||
@with_kw_noshow struct Tests <: BasicPlugin
|
||||
file::String = default_file("test", "runtests.jl")
|
||||
project::Bool = false
|
||||
end
|
||||
|
||||
source(p::Tests) = p.file
|
||||
destination(::Tests) = joinpath("test", "runtests.jl")
|
||||
view(::Tests, ::Template, pkg::AbstractString) = Dict("PKG" => pkg)
|
||||
|
||||
function prehook(p::Tests, t::Template, pkg_dir::AbstractString)
|
||||
invoke(prehook, Tuple{BasicPlugin, Template, AbstractString}, p, t, pkg_dir)
|
||||
p.project && t.julia_version < v"1.2" && @warn string(
|
||||
"Tests: The project option is set to create a project (supported in Julia 1.2 and later) ",
|
||||
"but a Julia version older than 1.2 is supported by the Template.",
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
function hook(p::Tests, t::Template, pkg_dir::AbstractString)
|
||||
# Do the normal BasicPlugin behaviour to create the test script.
|
||||
invoke(hook, Tuple{BasicPlugin, Template, AbstractString}, p, t, pkg_dir)
|
||||
|
||||
# Then set up the test depdendency in the chosen way.
|
||||
f = p.project ? make_test_project : add_test_dependency
|
||||
f(pkg_dir)
|
||||
end
|
||||
|
||||
# Create a new test project.
|
||||
function make_test_project(pkg_dir::AbstractString)
|
||||
with_project(() -> Pkg.add(TEST_DEP), joinpath(pkg_dir, "test"))
|
||||
end
|
||||
|
||||
# Add Test as a test-only dependency.
|
||||
function add_test_dependency(pkg_dir::AbstractString)
|
||||
# Add the dependency manually since there's no programmatic way to add to [extras].
|
||||
path = joinpath(pkg_dir, "Project.toml")
|
||||
toml = TOML.parsefile(path)
|
||||
get!(toml, "extras", Dict())["Test"] = TEST_UUID
|
||||
get!(toml, "targets", Dict())["test"] = ["Test"]
|
||||
open(io -> TOML.print(io, toml), path, "w")
|
||||
|
||||
# Generate the manifest by updating the project.
|
||||
# This also ensures that keys in Project.toml are sorted properly.
|
||||
touch(joinpath(pkg_dir, "Manifest.toml")) # File must exist to be modified by Pkg.
|
||||
with_project(Pkg.update, pkg_dir)
|
||||
end
|
87
src/plugins/git.jl
Normal file
87
src/plugins/git.jl
Normal file
@ -0,0 +1,87 @@
|
||||
"""
|
||||
Git(; ignore=String[], ssh=false, manifest=false, gpgsign=false)
|
||||
|
||||
Creates a Git repository and a `.gitignore` file.
|
||||
|
||||
## Keyword Arguments
|
||||
- `ignore::Vector{<:AbstractString}`: Patterns to add to the `.gitignore`.
|
||||
See also: [`gitignore`](@ref).
|
||||
- `manifest::Bool`: Whether or not to commit `Manifest.toml`.
|
||||
- `ssh::Bool`: Whether or not to use SSH for the remote.
|
||||
If left unset, HTTPS is used.
|
||||
- `gpgsign::Bool`: Whether or not to sign commits with your GPG key.
|
||||
This option requires that the Git CLI is installed.
|
||||
"""
|
||||
@with_kw_noshow struct Git <: Plugin
|
||||
ignore::Vector{String} = []
|
||||
ssh::Bool = false
|
||||
manifest::Bool = false
|
||||
gpgsign::Bool = false
|
||||
ignore_manifest::Bool = true
|
||||
end
|
||||
|
||||
Base.:(==)(a::Git, b::Git) = all(map(n -> getfield(a, n) == getfield(b, n), fieldnames(Git)))
|
||||
|
||||
function gitignore(p::Git)
|
||||
ignore = copy(p.ignore)
|
||||
p.manifest || push!(ignore, "Manifest.toml")
|
||||
return ignore
|
||||
end
|
||||
|
||||
# Set up the Git repository.
|
||||
function prehook(p::Git, t::Template, pkg_dir::AbstractString)
|
||||
if p.gpgsign && try run(pipeline(`git --version`; stdout=devnull)); false catch; true end
|
||||
throw(ArgumentError("Git: gpgsign is set but the Git CLI is not installed"))
|
||||
end
|
||||
LibGit2.with(LibGit2.init(pkg_dir)) do repo
|
||||
commit(p, repo, pkg_dir, "Initial commit")
|
||||
pkg = basename(pkg_dir)
|
||||
url = if p.ssh
|
||||
"git@$(t.host):$(t.user)/$pkg.jl.git"
|
||||
else
|
||||
"https://$(t.host)/$(t.user)/$pkg.jl"
|
||||
end
|
||||
LibGit2.with(GitRemote(repo, "origin", url)) do remote
|
||||
# TODO: `git pull` still requires some Git branch config.
|
||||
LibGit2.add_push!(repo, remote, "refs/heads/master")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Create the .gitignore.
|
||||
function hook(p::Git, t::Template, pkg_dir::AbstractString)
|
||||
ignore = mapreduce(gitignore, append!, values(t.plugins))
|
||||
# Only ignore manifests at the repo root.
|
||||
p.manifest || "Manifest.toml" in ignore || push!(ignore, "/Manifest.toml")
|
||||
unique!(sort!(ignore))
|
||||
gen_file(joinpath(pkg_dir, ".gitignore"), join(ignore, "\n"))
|
||||
end
|
||||
|
||||
# Commit the files
|
||||
function posthook(p::Git, t::Template, pkg_dir::AbstractString)
|
||||
# Ensure that the manifest exists if it's going to be committed.
|
||||
manifest = joinpath(pkg_dir, "Manifest.toml")
|
||||
if p.manifest && !isfile(manifest)
|
||||
touch(manifest)
|
||||
with_project(Pkg.update, pkg_dir)
|
||||
end
|
||||
|
||||
LibGit2.with(GitRepo(pkg_dir)) do repo
|
||||
LibGit2.add!(repo, ".")
|
||||
msg = "Files generated by PkgTemplates"
|
||||
installed = Pkg.installed()
|
||||
if haskey(installed, "PkgTemplates")
|
||||
ver = string(installed["PkgTemplates"])
|
||||
msg *= "\n\nPkgTemplates version: $ver"
|
||||
end
|
||||
commit(p, repo, pkg_dir, msg)
|
||||
end
|
||||
end
|
||||
|
||||
function commit(p::Git, repo::GitRepo, pkg_dir::AbstractString, msg::AbstractString)
|
||||
if p.gpgsign
|
||||
run(pipeline(`git -C $pkg_dir commit -S --allow-empty -m $msg`; stdout=devnull))
|
||||
else
|
||||
LibGit2.commit(repo, msg)
|
||||
end
|
||||
end
|
37
src/plugins/license.jl
Normal file
37
src/plugins/license.jl
Normal file
@ -0,0 +1,37 @@
|
||||
"""
|
||||
License(; name="MIT", path=nothing, destination="LICENSE")
|
||||
|
||||
Creates a license file.
|
||||
|
||||
## Keyword Arguments
|
||||
- `name::AbstractString`: Name of a license supported by PkgTemplates.
|
||||
Available licenses can be seen [here](https://github.com/invenia/PkgTemplates.jl/tree/master/templates/licenses).
|
||||
- `path::Union{AbstractString, Nothing}`: Path to a custom license file.
|
||||
This keyword takes priority over `name`.
|
||||
- `destination::AbstractString`: File destination, relative to the repository root.
|
||||
For example, `"LICENSE.md"` might be desired.
|
||||
"""
|
||||
struct License <: BasicPlugin
|
||||
path::String
|
||||
destination::String
|
||||
end
|
||||
|
||||
function License(
|
||||
name::AbstractString="MIT",
|
||||
path::Union{AbstractString, Nothing}=nothing,
|
||||
destination::AbstractString="LICENSE",
|
||||
)
|
||||
if path === nothing
|
||||
path = default_file("licenses", name)
|
||||
isfile(path) || throw(ArgumentError("License '$(basename(path))' is not available"))
|
||||
end
|
||||
return License(path, destination)
|
||||
end
|
||||
|
||||
|
||||
source(p::License) = p.path
|
||||
destination(p::License) = p.destination
|
||||
view(::License, t::Template, ::AbstractString) = Dict(
|
||||
"AUTHORS" => join(t.authors, ", "),
|
||||
"YEAR" => year(today()),
|
||||
)
|
33
src/plugins/project_file.jl
Normal file
33
src/plugins/project_file.jl
Normal file
@ -0,0 +1,33 @@
|
||||
"""
|
||||
ProjectFile()
|
||||
|
||||
Creates a `Project.toml`.
|
||||
"""
|
||||
struct ProjectFile <: Plugin end
|
||||
|
||||
# Create Project.toml in the prehook because other hooks might depend on it.
|
||||
function prehook(::ProjectFile, t::Template, pkg_dir::AbstractString)
|
||||
toml = Dict(
|
||||
"name" => basename(pkg_dir),
|
||||
"uuid" => uuid4(),
|
||||
"authors" => t.authors,
|
||||
"version" => "0.1.0",
|
||||
"compat" => Dict("julia" => compat_version(t.julia_version)),
|
||||
)
|
||||
open(io -> TOML.print(io, toml), joinpath(pkg_dir, "Project.toml"), "w")
|
||||
end
|
||||
|
||||
"""
|
||||
compat_version(v::VersionNumber) -> String
|
||||
|
||||
Format a `VersionNumber` to exclude trailing zero components.
|
||||
"""
|
||||
function compat_version(v::VersionNumber)
|
||||
return if v.patch == 0 && v.minor == 0
|
||||
"$(v.major)"
|
||||
elseif v.patch == 0
|
||||
"$(v.major).$(v.minor)"
|
||||
else
|
||||
"$(v.major).$(v.minor).$(v.patch)"
|
||||
end
|
||||
end
|
59
src/plugins/readme.jl
Normal file
59
src/plugins/readme.jl
Normal file
@ -0,0 +1,59 @@
|
||||
"""
|
||||
Readme(;
|
||||
file="$(contractuser(default_file("README.md")))",
|
||||
destination="README.md",
|
||||
inline_badges=false,
|
||||
)
|
||||
|
||||
Creates a `README` file.
|
||||
By default, it includes badges for other included plugins
|
||||
|
||||
## Keyword Arguments
|
||||
- `file::AbstractString`: Template file for the `README`.
|
||||
- `destination::AbstractString`: File destination, relative to the repository root.
|
||||
For example, values of `"README"` or `"README.rst"` might be desired.
|
||||
- `inline_badges::Bool`: Whether or not to put the badges on the same line as the package name.
|
||||
"""
|
||||
@with_kw_noshow struct Readme <: BasicPlugin
|
||||
file::String = default_file("README.md")
|
||||
destination::String = "README.md"
|
||||
inline_badges::Bool = false
|
||||
end
|
||||
|
||||
source(p::Readme) = p.file
|
||||
destination(p::Readme) = p.destination
|
||||
|
||||
function view(p::Readme, t::Template, pkg::AbstractString)
|
||||
# Explicitly ordered badges go first.
|
||||
strings = String[]
|
||||
done = DataType[]
|
||||
foreach(badge_order()) do T
|
||||
if hasplugin(t, T)
|
||||
bs = badges(t.plugins[T], t, pkg)
|
||||
append!(strings, badges(t.plugins[T], t, pkg))
|
||||
push!(done, T)
|
||||
end
|
||||
end
|
||||
foreach(setdiff(keys(t.plugins), done)) do T
|
||||
bs = badges(t.plugins[T], t, pkg)
|
||||
append!(strings, badges(t.plugins[T], t, pkg))
|
||||
end
|
||||
|
||||
return Dict(
|
||||
"BADGES" => strings,
|
||||
"HAS_CITATION" => hasplugin(t, Citation) && t.plugins[Citation].readme,
|
||||
"HAS_INLINE_BADGES" => !isempty(strings) && p.inline_badges,
|
||||
"PKG" => pkg,
|
||||
)
|
||||
end
|
||||
|
||||
badge_order() = [
|
||||
Documenter{GitLabCI},
|
||||
Documenter{TravisCI},
|
||||
GitLabCI,
|
||||
TravisCI,
|
||||
AppVeyor,
|
||||
CirrusCI,
|
||||
Codecov,
|
||||
Coveralls,
|
||||
]
|
29
src/plugins/src_dir.jl
Normal file
29
src/plugins/src_dir.jl
Normal file
@ -0,0 +1,29 @@
|
||||
"""
|
||||
SrcDir(; file="$(contractuser(default_file("src", "module.jl")))")
|
||||
|
||||
Creates a module entrypoint.
|
||||
"""
|
||||
@with_kw_noshow mutable struct SrcDir <: BasicPlugin
|
||||
file::String = default_file("src", "module.jl")
|
||||
destination::String = joinpath("src", "<module>.jl")
|
||||
end
|
||||
|
||||
Base.:(==)(a::SrcDir, b::SrcDir) = a.file == b.file
|
||||
|
||||
# Don't display the destination field.
|
||||
function Base.show(io::IO, ::MIME"text/plain", p::SrcDir)
|
||||
indent = get(io, :indent, 0)
|
||||
print(io, repeat(' ', indent), "SrcDir:")
|
||||
print(io, "\n", repeat(' ', indent + 2), "file: ", show_field(p.file))
|
||||
end
|
||||
|
||||
source(p::SrcDir) = p.file
|
||||
destination(p::SrcDir) = p.destination
|
||||
view(::SrcDir, ::Template, pkg::AbstractString) = Dict("PKG" => pkg)
|
||||
|
||||
# Update the destination now that we know the package name.
|
||||
# Kind of hacky, but oh well.
|
||||
function prehook(p::SrcDir, t::Template, pkg_dir::AbstractString)
|
||||
invoke(prehook, Tuple{BasicPlugin, Template, AbstractString}, p, t, pkg_dir)
|
||||
p.destination = joinpath("src", basename(pkg_dir) * ".jl")
|
||||
end
|
62
src/plugins/tests.jl
Normal file
62
src/plugins/tests.jl
Normal file
@ -0,0 +1,62 @@
|
||||
const TEST_UUID = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
const TEST_DEP = PackageSpec(; name="Test", uuid=TEST_UUID)
|
||||
|
||||
"""
|
||||
Tests(; file="$(contractuser(default_file("test", "runtests.jl")))", project=false)
|
||||
|
||||
Sets up testing for packages.
|
||||
|
||||
## Keyword Arguments
|
||||
- `file::AbstractString`: Template file for the `runtests.jl`.
|
||||
- `project::Bool`: Whether or not to create a new project for tests (`test/Project.toml`).
|
||||
See [here](https://julialang.github.io/Pkg.jl/v1/creating-packages/#Test-specific-dependencies-in-Julia-1.2-and-above-1) for more details.
|
||||
|
||||
!!! note
|
||||
Managing test dependencies with `test/Project.toml` is only supported in Julia 1.2 and later.
|
||||
"""
|
||||
@with_kw_noshow struct Tests <: BasicPlugin
|
||||
file::String = default_file("test", "runtests.jl")
|
||||
project::Bool = false
|
||||
end
|
||||
|
||||
source(p::Tests) = p.file
|
||||
destination(::Tests) = joinpath("test", "runtests.jl")
|
||||
view(::Tests, ::Template, pkg::AbstractString) = Dict("PKG" => pkg)
|
||||
|
||||
function prehook(p::Tests, t::Template, pkg_dir::AbstractString)
|
||||
invoke(prehook, Tuple{BasicPlugin, Template, AbstractString}, p, t, pkg_dir)
|
||||
p.project && t.julia_version < v"1.2" && @warn string(
|
||||
"Tests: The project option is set to create a project (supported in Julia 1.2 and later) ",
|
||||
"but a Julia version older than 1.2 is supported by the Template.",
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
function hook(p::Tests, t::Template, pkg_dir::AbstractString)
|
||||
# Do the normal BasicPlugin behaviour to create the test script.
|
||||
invoke(hook, Tuple{BasicPlugin, Template, AbstractString}, p, t, pkg_dir)
|
||||
|
||||
# Then set up the test depdendency in the chosen way.
|
||||
f = p.project ? make_test_project : add_test_dependency
|
||||
f(pkg_dir)
|
||||
end
|
||||
|
||||
# Create a new test project.
|
||||
function make_test_project(pkg_dir::AbstractString)
|
||||
with_project(() -> Pkg.add(TEST_DEP), joinpath(pkg_dir, "test"))
|
||||
end
|
||||
|
||||
# Add Test as a test-only dependency.
|
||||
function add_test_dependency(pkg_dir::AbstractString)
|
||||
# Add the dependency manually since there's no programmatic way to add to [extras].
|
||||
path = joinpath(pkg_dir, "Project.toml")
|
||||
toml = TOML.parsefile(path)
|
||||
get!(toml, "extras", Dict())["Test"] = TEST_UUID
|
||||
get!(toml, "targets", Dict())["test"] = ["Test"]
|
||||
open(io -> TOML.print(io, toml), path, "w")
|
||||
|
||||
# Generate the manifest by updating the project.
|
||||
# This also ensures that keys in Project.toml are sorted properly.
|
||||
touch(joinpath(pkg_dir, "Manifest.toml")) # File must exist to be modified by Pkg.
|
||||
with_project(Pkg.update, pkg_dir)
|
||||
end
|
3
test/fixtures/AllPlugins/.gitignore
vendored
3
test/fixtures/AllPlugins/.gitignore
vendored
@ -1,7 +1,6 @@
|
||||
*.jl.*.cov
|
||||
*.jl.cov
|
||||
*.jl.mem
|
||||
.DS_Store
|
||||
/dev/
|
||||
/docs/build/
|
||||
/docs/site/
|
||||
Manifest.toml
|
||||
|
4
test/fixtures/AllPlugins/src/AllPlugins.jl
vendored
4
test/fixtures/AllPlugins/src/AllPlugins.jl
vendored
@ -1,5 +1,5 @@
|
||||
module AllPlugins
|
||||
|
||||
greet() = print("Hello World!")
|
||||
# Write your package code here.
|
||||
|
||||
end # module
|
||||
end
|
||||
|
3
test/fixtures/Basic/.gitignore
vendored
3
test/fixtures/Basic/.gitignore
vendored
@ -1,2 +1 @@
|
||||
.DS_Store
|
||||
/dev/
|
||||
Manifest.toml
|
||||
|
4
test/fixtures/Basic/src/Basic.jl
vendored
4
test/fixtures/Basic/src/Basic.jl
vendored
@ -1,5 +1,5 @@
|
||||
module Basic
|
||||
|
||||
greet() = print("Hello World!")
|
||||
# Write your package code here.
|
||||
|
||||
end # module
|
||||
end
|
||||
|
10
test/git.jl
10
test/git.jl
@ -6,7 +6,7 @@ end
|
||||
|
||||
@testset "Git repositories" begin
|
||||
@testset "Does not create Git repo" begin
|
||||
t = tpl(; git=false)
|
||||
t = tpl(; disable_defaults=[Git])
|
||||
with_pkg(t) do pkg
|
||||
pkg_dir = joinpath(t.dir, pkg)
|
||||
@test !isdir(joinpath(pkg_dir, ".git"))
|
||||
@ -14,7 +14,7 @@ end
|
||||
end
|
||||
|
||||
@testset "Creates Git repo" begin
|
||||
t = tpl(; git=true)
|
||||
t = tpl(; plugins=[Git()])
|
||||
with_pkg(t) do pkg
|
||||
pkg_dir = joinpath(t.dir, pkg)
|
||||
@test isdir(joinpath(pkg_dir, ".git"))
|
||||
@ -22,7 +22,7 @@ end
|
||||
end
|
||||
|
||||
@testset "With HTTPS" begin
|
||||
t = tpl(; git=true, ssh=false)
|
||||
t = tpl(; plugins=[Git(; ssh=false)])
|
||||
with_pkg(t) do pkg
|
||||
LibGit2.with(GitRepo(joinpath(t.dir, pkg))) do repo
|
||||
remote = LibGit2.get(GitRemote, repo, "origin")
|
||||
@ -32,7 +32,7 @@ end
|
||||
end
|
||||
|
||||
@testset "With SSH" begin
|
||||
t = tpl(; git=true, ssh=true)
|
||||
t = tpl(; plugins=[Git(; ssh=true)])
|
||||
with_pkg(t) do pkg
|
||||
LibGit2.with(GitRepo(joinpath(t.dir, pkg))) do repo
|
||||
remote = LibGit2.get(GitRemote, repo, "origin")
|
||||
@ -43,7 +43,7 @@ end
|
||||
|
||||
@testset "Adds version to commit message" begin
|
||||
# We're careful to avoid a Pkg.update as it triggers Cassette#130.
|
||||
t = tpl(; git=true, develop=false, disable_defaults=[Tests])
|
||||
t = tpl(; disable_defaults=[Tests], plugins=[Git()])
|
||||
@overdub PTIsInstalled() with_pkg(t) do pkg
|
||||
pkg_dir = joinpath(t.dir, pkg)
|
||||
LibGit2.with(GitRepo(pkg_dir)) do repo
|
||||
|
@ -23,8 +23,12 @@ end
|
||||
|
||||
@testset "All plugins" begin
|
||||
test_all("AllPlugins"; authors=USER, manifest=true, plugins=[
|
||||
AppVeyor(), CirrusCI(), Citation(), Codecov(),
|
||||
Coveralls(), Documenter(), GitLabCI(), TravisCI(),
|
||||
AppVeyor(), CirrusCI(), Citation(), Codecov(), Coveralls(),
|
||||
Develop(), Documenter(), GitLabCI(), TravisCI(),
|
||||
])
|
||||
end
|
||||
|
||||
@testset "Wacky options" begin
|
||||
# TODO
|
||||
end
|
||||
end
|
||||
|
@ -19,10 +19,10 @@ Random.seed!(1)
|
||||
# Creata a template that won't error because of a missing username.
|
||||
tpl(; kwargs...) = Template(; user=USER, kwargs...)
|
||||
|
||||
const pkg_name = Ref("A")
|
||||
const PKG = Ref("A")
|
||||
|
||||
# Generate an unused package name.
|
||||
pkgname() = pkg_name[] *= "a"
|
||||
pkgname() = PKG[] *= "a"
|
||||
|
||||
# Create a randomly named package with a template, and delete it afterwards.
|
||||
function with_pkg(f::Function, t::Template, pkg::AbstractString=pkgname())
|
||||
|
41
test/show.jl
41
test/show.jl
@ -1,11 +1,11 @@
|
||||
const DEFAULTS_DIR = contractuser(PT.DEFAULTS_DIR)
|
||||
const LICENSE_DIR = contractuser(joinpath(PT.DEFAULTS_DIR, "licenses"))
|
||||
const TEMPLATES_DIR = contractuser(PT.TEMPLATES_DIR)
|
||||
const LICENSES_DIR = joinpath(TEMPLATES_DIR, "licenses")
|
||||
|
||||
@testset "Show methods" begin
|
||||
@testset "Plugins" begin
|
||||
expected = """
|
||||
Readme:
|
||||
file: "$(joinpath(DEFAULTS_DIR, "README.md"))"
|
||||
file: "$(joinpath(TEMPLATES_DIR, "README.md"))"
|
||||
destination: "README.md"
|
||||
inline_badges: false
|
||||
"""
|
||||
@ -15,28 +15,39 @@ const LICENSE_DIR = contractuser(joinpath(PT.DEFAULTS_DIR, "licenses"))
|
||||
@testset "Template" begin
|
||||
expected = """
|
||||
Template:
|
||||
authors: ["$USER"]
|
||||
develop: true
|
||||
dir: "$(contractuser(Pkg.devdir()))"
|
||||
git: true
|
||||
authors: ["Chris de Graaf <chrisadegraaf@gmail.com>"]
|
||||
dir: "~/.local/share/julia/dev"
|
||||
host: "github.com"
|
||||
julia_version: v"1.0.0"
|
||||
manifest: false
|
||||
ssh: false
|
||||
user: "$USER"
|
||||
plugins:
|
||||
Gitignore:
|
||||
ds_store: true
|
||||
dev: true
|
||||
"""
|
||||
expected = """
|
||||
Template:
|
||||
authors: ["$USER"]
|
||||
dir: "$(contractuser(Pkg.devdir()))"
|
||||
host: "github.com"
|
||||
julia_version: v"1.0.0"
|
||||
user: "$USER"
|
||||
plugins:
|
||||
Git:
|
||||
ignore: String[]
|
||||
ssh: false
|
||||
manifest: false
|
||||
gpgsign: false
|
||||
ignore_manifest: true
|
||||
License:
|
||||
path: "$(joinpath(LICENSE_DIR, "MIT"))"
|
||||
path: "$(joinpath(LICENSES_DIR, "MIT"))"
|
||||
destination: "LICENSE"
|
||||
ProjectFile:
|
||||
Readme:
|
||||
file: "$(joinpath(DEFAULTS_DIR, "README.md"))"
|
||||
file: "$(joinpath(TEMPLATES_DIR, "README.md"))"
|
||||
destination: "README.md"
|
||||
inline_badges: false
|
||||
SrcDir:
|
||||
file: "$(joinpath(TEMPLATES_DIR, "src", "module.jl"))"
|
||||
Tests:
|
||||
file: "$(joinpath(DEFAULTS_DIR, "test", "runtests.jl"))"
|
||||
file: "$(joinpath(TEMPLATES_DIR, "test", "runtests.jl"))"
|
||||
project: false
|
||||
"""
|
||||
@test sprint(show, MIME("text/plain"), tpl(; authors=USER)) == rstrip(expected)
|
||||
|
@ -35,10 +35,11 @@
|
||||
test_plugins([], defaults)
|
||||
test_plugins([Citation()], union(defaults, [Citation()]))
|
||||
# Overriding a default plugin.
|
||||
gi = Gitignore(; dev=false)
|
||||
test_plugins([gi], union(setdiff(defaults, [Gitignore()]), [gi]))
|
||||
default_g = defaults[findfirst(p -> p isa Git, defaults)]
|
||||
g = Git(; ssh=true)
|
||||
test_plugins([g], union(setdiff(defaults, [default_g]), [g]))
|
||||
# Disabling a default plugin.
|
||||
test_plugins([], setdiff(defaults, [Gitignore()]), [Gitignore])
|
||||
test_plugins([], setdiff(defaults, [default_g]), [Git])
|
||||
end
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user