The Big Squash: A bunch of irrelevant garbage
This commit is contained in:
parent
895f2be769
commit
c0fe7bb2c2
@ -1,27 +0,0 @@
|
||||
environment:
|
||||
matrix:
|
||||
- julia_version: 0.7
|
||||
- julia_version: 1.0
|
||||
- julia_version: nightly
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
matrix:
|
||||
allow_failures:
|
||||
- julia_version: nightly
|
||||
notifications:
|
||||
- provider: Email
|
||||
on_build_success: false
|
||||
on_build_failure: false
|
||||
on_build_status_changed: false
|
||||
install:
|
||||
- ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1"))
|
||||
build_script:
|
||||
- echo "%JL_BUILD_SCRIPT%"
|
||||
- C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%"
|
||||
test_script:
|
||||
- echo "%JL_TEST_SCRIPT%"
|
||||
- C:\julia\bin\julia -e "%JL_TEST_SCRIPT%"
|
||||
on_success:
|
||||
- echo "%JL_CODECOV_SCRIPT%"
|
||||
- C:\julia\bin\julia -e "%JL_CODECOV_SCRIPT%"
|
@ -1 +0,0 @@
|
||||
comment: false
|
20
.travis.yml
20
.travis.yml
@ -2,9 +2,10 @@ language: julia
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
- windows
|
||||
julia:
|
||||
- 1.0
|
||||
- 1.1
|
||||
- 1.2
|
||||
- nightly
|
||||
matrix:
|
||||
allow_failures:
|
||||
@ -12,14 +13,19 @@ matrix:
|
||||
fast_finish: true
|
||||
notifications:
|
||||
email: false
|
||||
after_success: julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())'
|
||||
after_success:
|
||||
- julia -e '
|
||||
using Pkg
|
||||
Pkg.add("Coverage")
|
||||
using Coverage
|
||||
Codecov.submit(process_folder())'
|
||||
jobs:
|
||||
include:
|
||||
- stage: Documentation
|
||||
julia: 1.1
|
||||
julia: 1.2
|
||||
script: julia --project=docs -e '
|
||||
using Pkg;
|
||||
Pkg.develop(PackageSpec(path=pwd()));
|
||||
Pkg.instantiate();
|
||||
include("docs/make.jl");'
|
||||
using Pkg
|
||||
Pkg.develop(PackageSpec(; path=pwd()))
|
||||
Pkg.instantiate()
|
||||
include("docs/make.jl")'
|
||||
after_success: skip
|
||||
|
@ -3,6 +3,16 @@
|
||||
[[Base64]]
|
||||
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||
|
||||
[[DataAPI]]
|
||||
git-tree-sha1 = "8903f0219d3472543fc4b2f5ebaf675a07f817c0"
|
||||
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
|
||||
version = "1.0.1"
|
||||
|
||||
[[DataValueInterfaces]]
|
||||
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
|
||||
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
|
||||
version = "1.0.0"
|
||||
|
||||
[[Dates]]
|
||||
deps = ["Printf"]
|
||||
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
@ -39,9 +49,9 @@ uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
|
||||
|
||||
[[Mustache]]
|
||||
deps = ["Printf", "Tables"]
|
||||
git-tree-sha1 = "d27b8b8b99c052ea1fdd40c678bfb2dfaec4e96e"
|
||||
git-tree-sha1 = "f39de3a12232eb47bd0629b3a661054287780276"
|
||||
uuid = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
|
||||
version = "0.5.12"
|
||||
version = "0.5.13"
|
||||
|
||||
[[Pkg]]
|
||||
deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
|
||||
@ -59,12 +69,6 @@ uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
|
||||
deps = ["Serialization"]
|
||||
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||
|
||||
[[Requires]]
|
||||
deps = ["Test"]
|
||||
git-tree-sha1 = "f6fbf4ba64d295e146e49e021207993b6b48c7d1"
|
||||
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
|
||||
version = "0.5.2"
|
||||
|
||||
[[SHA]]
|
||||
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
|
||||
|
||||
@ -81,10 +85,10 @@ uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
|
||||
version = "1.0.0"
|
||||
|
||||
[[Tables]]
|
||||
deps = ["IteratorInterfaceExtensions", "LinearAlgebra", "Requires", "TableTraits", "Test"]
|
||||
git-tree-sha1 = "351a4b894122e1553c6ed05fda54086ab036adef"
|
||||
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"]
|
||||
git-tree-sha1 = "aaed7b3b00248ff6a794375ad6adf30f30ca5591"
|
||||
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
|
||||
version = "0.2.5"
|
||||
version = "0.2.11"
|
||||
|
||||
[[Test]]
|
||||
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
|
||||
|
@ -16,7 +16,8 @@ URIParser = "30578b45-9adc-5946-b283-645ec420af67"
|
||||
julia = "1"
|
||||
|
||||
[extras]
|
||||
Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
|
||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
|
||||
[targets]
|
||||
test = ["Test"]
|
||||
test = ["Suppressor", "Test"]
|
||||
|
8
defaults/CITATION.bib
Normal file
8
defaults/CITATION.bib
Normal file
@ -0,0 +1,8 @@
|
||||
@misc{<<PKG>>.jl,
|
||||
author = {<<AUTHORS>>},
|
||||
title = {<<PKG>>.jl},
|
||||
url = {<<URL>>},
|
||||
version = {v0.1.0},
|
||||
year = {<<YEAR>>},
|
||||
month = {<<MONTH>>}
|
||||
}
|
13
defaults/README.md
Normal file
13
defaults/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# {{PKG}}{{#HAS_INLINE_BADGES}} {{#BADGES}}{{.}} {{/BADGES}}{{/HAS_INLINE_BADGES}}
|
||||
{{^HAS_INLINE_BADGES}}
|
||||
|
||||
{{#BADGES}}
|
||||
{{.}}
|
||||
{{/BADGES}}
|
||||
{{/HAS_INLINE_BADGES}}
|
||||
{{#HAS_CITATION}}
|
||||
|
||||
## Citing
|
||||
|
||||
See [`CITATION.bib`](CITATION.bib) for the relevant reference(s).
|
||||
{{/HAS_CITATION}}
|
@ -1,14 +1,18 @@
|
||||
# Documentation: https://github.com/JuliaCI/Appveyor.jl
|
||||
environment:
|
||||
matrix:
|
||||
- julia_version: {{VERSION}}
|
||||
- julia_version: nightly
|
||||
{{#VERSIONS}}
|
||||
- julia_version: {{.}}
|
||||
{{/VERSIONS}}
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
{{#PLATFORMS}}
|
||||
- {{.}}
|
||||
{{/PLATFORMS}}
|
||||
{{#HAS_NIGHTLY}}
|
||||
matrix:
|
||||
allow_failures:
|
||||
- julia_version: nightly
|
||||
{{/HAS_NIGHTLY}}
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
@ -26,8 +30,8 @@ build_script:
|
||||
test_script:
|
||||
- echo "%JL_TEST_SCRIPT%"
|
||||
- C:\julia\bin\julia -e "%JL_TEST_SCRIPT%"
|
||||
{{#CODECOV}}
|
||||
{{#HAS_CODECOV}}
|
||||
on_success:
|
||||
- echo "%JL_CODECOV_SCRIPT%"
|
||||
- C:\julia\bin\julia -e "%JL_CODECOV_SCRIPT%"
|
||||
{{/CODECOV}}
|
||||
{{/HAS_CODECOV}}
|
||||
|
@ -1,16 +1,18 @@
|
||||
freebsd_instance:
|
||||
image: freebsd-12-0-release-amd64
|
||||
image: {{IMAGE}}
|
||||
task:
|
||||
name: FreeBSD
|
||||
env:
|
||||
JULIA_VERSION: {{VERSION}}
|
||||
{{#VERSIONS}}
|
||||
JULIA_VERSION: {{.}}
|
||||
{{/VERSIONS}}
|
||||
install_script:
|
||||
- sh -c "$(fetch https://raw.githubusercontent.com/ararslan/CirrusCI.jl/master/bin/install.sh -o -)"
|
||||
build_script:
|
||||
- cirrusjl build
|
||||
test_script:
|
||||
- cirrusjl test
|
||||
{{#COVERAGE}}
|
||||
{{#HAS_COVERAGE}}
|
||||
coverage_script:
|
||||
- cirrusjl coverage{{#CODECOV}} codecov{{/CODECOV}}{{#COVERALLS}} coveralls{{/COVERALLS}}
|
||||
{{/COVERAGE}}
|
||||
- cirrusjl coverage{{#HAS_CODECOV}} codecov{{/HAS_CODECOV}}{{#HAS_COVERALLS}} coveralls{{/HAS_COVERALLS}}
|
||||
{{/HAS_COVERAGE}}
|
||||
|
@ -1,19 +1,30 @@
|
||||
Julia {{VERSION}}:
|
||||
image: julia:{{VERSION}}
|
||||
script: julia --project='@.' -e 'using Pkg; Pkg.build(); Pkg.test({{#GITLABCOVERAGE}}; coverage=true{{/GITLABCOVERAGE}})'
|
||||
{{#GITLABCOVERAGE}}
|
||||
{{#VERSIONS}}
|
||||
Julia {{.}}:
|
||||
image: julia:{{.}}
|
||||
script: julia --project=@. -e '
|
||||
using Pkg
|
||||
Pkg.build()
|
||||
Pkg.test({{#HAS_COVERAGE}}coverage=true{{/HAS_COVERAGE}})'
|
||||
{{/VERSIONS}}
|
||||
{{#HAS_COVERAGE}}
|
||||
coverage: /Test Coverage (\d+\.\d+%)/
|
||||
after_script:
|
||||
- julia -e 'using Printf; using Pkg; Pkg.add("Coverage"); using Coverage; c, t = get_summary(process_folder()); @printf "Test Coverage %.2f%%\n" 100c/t'
|
||||
{{/GITLABCOVERAGE}}
|
||||
{{#DOCUMENTER}}
|
||||
- julia -e '
|
||||
using Pkg
|
||||
Pkg.add("Coverage")
|
||||
using Coverage
|
||||
c, t = get_summary(process_folder())
|
||||
using Printf
|
||||
@printf "Test Coverage %.2f%%\n" 100c/t'
|
||||
{{/HAS_COVERAGE}}
|
||||
{{#HAS_DOCUMENTER}}
|
||||
pages:
|
||||
image: julia:{{VERSION}}
|
||||
stage: deploy
|
||||
script:
|
||||
- julia --project=docs -e '
|
||||
using Pkg;
|
||||
Pkg.develop(PackageSpec(path=pwd()));
|
||||
Pkg.develop(PackageSpec(; path=pwd()));
|
||||
Pkg.instantiate();
|
||||
include("docs/make.jl");'
|
||||
- mkdir -p public
|
||||
@ -23,4 +34,4 @@ pages:
|
||||
- public
|
||||
only:
|
||||
- master
|
||||
{{/DOCUMENTER}}
|
||||
{{/HAS_DOCUMENTER}}
|
||||
|
8
defaults/index.md
Normal file
8
defaults/index.md
Normal file
@ -0,0 +1,8 @@
|
||||
# {{PKG}}
|
||||
|
||||
```@index
|
||||
```
|
||||
|
||||
```@autodocs
|
||||
Modules = [{{PKG}}]
|
||||
```
|
31
defaults/make.jl
Normal file
31
defaults/make.jl
Normal file
@ -0,0 +1,31 @@
|
||||
using {{PKG}}
|
||||
using Documenter
|
||||
|
||||
makedocs(
|
||||
modules=[{{PKG}}],
|
||||
authors="{{AUTHORS}}",
|
||||
repo="{{REPO}}",
|
||||
sitename="{{PKG}}.jl",
|
||||
format=Documenter.HTML(;
|
||||
canonical="{{CANONICAL}}",
|
||||
assets={{^HAS_ASSETS}}String{{/HAS_ASSETS}}[{{^HAS_ASSETS}}],{{/HAS_ASSETS}}
|
||||
{{#ASSETS}}
|
||||
"{{.}}",
|
||||
{{/ASSETS}}
|
||||
{{#HAS_ASSETS}}
|
||||
],
|
||||
{{/HAS_ASSETS}}
|
||||
),
|
||||
pages=[
|
||||
"Home" => "index.md",
|
||||
],
|
||||
{{#MAKEDOCS_KWARGS}}
|
||||
{{first}}={{second}},
|
||||
{{/MAKEDOCS_KWARGS}}
|
||||
)
|
||||
{{#HAS_DEPLOY}}
|
||||
|
||||
deploydocs(;
|
||||
repo="{{REPO}}",
|
||||
)
|
||||
{{/HAS_DEPLOY}}
|
6
defaults/runtests.jl
Normal file
6
defaults/runtests.jl
Normal file
@ -0,0 +1,6 @@
|
||||
using {{PKG}}
|
||||
using Test
|
||||
|
||||
@testset "{{PKG}}.jl" begin
|
||||
# Write your tests here.
|
||||
end
|
@ -1,35 +1,46 @@
|
||||
# Documentation: http://docs.travis-ci.com/user/languages/julia/
|
||||
# Documentation: http://docs.travis-ci.com/user/languages/julia
|
||||
language: julia
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
julia:
|
||||
- {{VERSION}}
|
||||
- nightly
|
||||
matrix:
|
||||
allow_failures:
|
||||
- julia: nightly
|
||||
fast_finish: true
|
||||
notifications:
|
||||
email: false
|
||||
{{#COVERAGE}}
|
||||
after_success:
|
||||
{{#CODECOV}}
|
||||
- julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())'
|
||||
{{/CODECOV}}
|
||||
{{#COVERALLS}}
|
||||
- julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder())'
|
||||
{{/COVERALLS}}
|
||||
{{/COVERAGE}}
|
||||
{{#DOCUMENTER}}
|
||||
{{#HAS_DOCUMENTER}}
|
||||
jobs:
|
||||
fast_finish: true
|
||||
{{#HAS_NIGHTLY}}
|
||||
allow_failures:
|
||||
- julia: nightly
|
||||
{{/HAS_NIGHTLY}}
|
||||
include:
|
||||
{{#JOBS}}
|
||||
- julia: {{JULIA}}
|
||||
os: {{OS}}
|
||||
{{#ARCH}}
|
||||
arch: {{ARCH}}
|
||||
{{/ARCH}}
|
||||
{{/JOBS}}
|
||||
{{#HAS_DOCUMENTER}}
|
||||
- stage: Documentation
|
||||
julia: {{VERSION}}
|
||||
script: julia --project=docs -e '
|
||||
using Pkg;
|
||||
Pkg.develop(PackageSpec(path=pwd()));
|
||||
Pkg.develop(PackageSpec(; path=pwd()));
|
||||
Pkg.instantiate();
|
||||
include("docs/make.jl");'
|
||||
after_success: skip
|
||||
{{/DOCUMENTER}}
|
||||
{{/HAS_DOCUMENTER}}
|
||||
{{#HAS_COVERAGE}}
|
||||
after_success:
|
||||
{{#HAS_CODECOV}}
|
||||
- julia -e '
|
||||
using Pkg;
|
||||
Pkg.add("Coverage");
|
||||
using Coverage;
|
||||
Codecov.submit(process_folder());'
|
||||
{{/HAS_CODECOV}}
|
||||
{{#HAS_COVERALLS}}
|
||||
- julia -e '
|
||||
using Pkg;
|
||||
Pkg.add("Coverage");
|
||||
using Coverage;
|
||||
Coveralls.submit(process_folder());'
|
||||
{{/HAS_COVERALLS}}
|
||||
{{/HAS_COVERAGE}}
|
||||
|
@ -1,3 +1,5 @@
|
||||
# This file is machine-generated - editing it directly is not advised
|
||||
|
||||
[[Base64]]
|
||||
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||
|
||||
@ -6,35 +8,34 @@ deps = ["Printf"]
|
||||
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
|
||||
[[Distributed]]
|
||||
deps = ["LinearAlgebra", "Random", "Serialization", "Sockets"]
|
||||
deps = ["Random", "Serialization", "Sockets"]
|
||||
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
|
||||
|
||||
[[DocStringExtensions]]
|
||||
deps = ["LibGit2", "Markdown", "Pkg", "Test"]
|
||||
git-tree-sha1 = "1df01539a1c952cef21f2d2d1c092c2bcf0177d7"
|
||||
git-tree-sha1 = "0513f1a8991e9d83255e0140aace0d0fc4486600"
|
||||
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
|
||||
version = "0.6.0"
|
||||
version = "0.8.0"
|
||||
|
||||
[[Documenter]]
|
||||
deps = ["Base64", "DocStringExtensions", "InteractiveUtils", "LibGit2", "Logging", "Markdown", "Pkg", "REPL", "Random", "Test", "Unicode"]
|
||||
git-tree-sha1 = "a6db1c69925cdc53aafb38caec4446be26e0c617"
|
||||
deps = ["Base64", "DocStringExtensions", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"]
|
||||
git-tree-sha1 = "c61d6eedbc3c4323c08b64af12d29c8ee0fcbb5f"
|
||||
uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
|
||||
version = "0.21.0"
|
||||
version = "0.23.2"
|
||||
|
||||
[[InteractiveUtils]]
|
||||
deps = ["LinearAlgebra", "Markdown"]
|
||||
deps = ["Markdown"]
|
||||
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
|
||||
|
||||
[[JSON]]
|
||||
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
|
||||
git-tree-sha1 = "b34d7cef7b337321e97d22242c3c2b91f476748e"
|
||||
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
|
||||
version = "0.21.0"
|
||||
|
||||
[[LibGit2]]
|
||||
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
|
||||
|
||||
[[Libdl]]
|
||||
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
|
||||
|
||||
[[LinearAlgebra]]
|
||||
deps = ["Libdl"]
|
||||
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
||||
|
||||
[[Logging]]
|
||||
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
||||
|
||||
@ -42,6 +43,15 @@ uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
||||
deps = ["Base64"]
|
||||
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
|
||||
|
||||
[[Mmap]]
|
||||
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
|
||||
|
||||
[[Parsers]]
|
||||
deps = ["Dates", "Test"]
|
||||
git-tree-sha1 = "db2b35dedab3c0e46dc15996d170af07a5ab91c9"
|
||||
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
|
||||
version = "0.3.6"
|
||||
|
||||
[[Pkg]]
|
||||
deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
|
||||
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
|
||||
@ -72,7 +82,7 @@ deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
|
||||
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
|
||||
[[UUIDs]]
|
||||
deps = ["Random"]
|
||||
deps = ["Random", "SHA"]
|
||||
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
||||
|
||||
[[Unicode]]
|
||||
|
@ -72,8 +72,7 @@ t = Template(;
|
||||
Codecov(),
|
||||
Coveralls(),
|
||||
AppVeyor(),
|
||||
GitHubPages(),
|
||||
CirrusCI(),
|
||||
Documenter{TravisCI}(),
|
||||
],
|
||||
)
|
||||
generate("MyPkg2", t)
|
||||
@ -103,5 +102,4 @@ include, you are encouraged to use [AttoBot](https://github.com/apps/attobot) in
|
||||
## Contributing
|
||||
|
||||
It's extremely easy to extend `PkgTemplates` with new plugins. To get started,
|
||||
check out the
|
||||
[plugin development guide](https://invenia.github.io/PkgTemplates.jl/stable/pages/plugin_development.html).
|
||||
check out [Plugin Development](@ref).
|
||||
|
@ -4,17 +4,11 @@ CurrentModule = PkgTemplates
|
||||
|
||||
# Licenses
|
||||
|
||||
[Many open-source licenses](https://github.com/christopher-dG/PkgTemplates.jl/tree/master/licenses)
|
||||
are available for use with `PkgTemplates`, but if you see that one is missing,
|
||||
don't hesitate to open an issue or PR.
|
||||
[Many open-source licenses](https://github.com/invenia/PkgTemplates.jl/tree/master/licenses)
|
||||
are available for use with `PkgTemplates`, but if you see that one is missing, don't
|
||||
hesitate to open an issue or PR.
|
||||
|
||||
```@docs
|
||||
available_licenses
|
||||
show_license
|
||||
```
|
||||
|
||||
### Helper Functions
|
||||
|
||||
```@docs
|
||||
read_license
|
||||
```
|
||||
|
@ -7,25 +7,9 @@ CurrentModule = PkgTemplates
|
||||
Creating new packages with `PkgTemplates` revolves around creating a new
|
||||
[`Template`](@ref), then calling [`generate`](@ref) on it.
|
||||
|
||||
## `Template`
|
||||
|
||||
```@docs
|
||||
Template
|
||||
interactive_template
|
||||
```
|
||||
|
||||
## `generate`
|
||||
|
||||
```@docs
|
||||
generate
|
||||
generate_interactive
|
||||
```
|
||||
|
||||
### Helper Functions
|
||||
|
||||
```@docs
|
||||
gen_tests
|
||||
gen_readme
|
||||
gen_gitignore
|
||||
gen_license
|
||||
```
|
||||
|
@ -4,72 +4,69 @@ CurrentModule = PkgTemplates
|
||||
|
||||
# Plugin Development
|
||||
|
||||
The best and easiest way to contribute to `PkgTemplates` is to write new
|
||||
plugins.
|
||||
The best and easiest way to contribute to `PkgTemplates` is to write new plugins.
|
||||
|
||||
```@docs
|
||||
Plugin
|
||||
```
|
||||
|
||||
## Generic Plugins
|
||||
## "Generic" Plugins
|
||||
|
||||
Many plugins fall into the category of managing some configuration file.
|
||||
Think Travis CI's `.travis.yml`, and so on for every CI service ever.
|
||||
For these one-file plugins, a shortcut macro is available to define a plugin in one line.
|
||||
|
||||
```@docs
|
||||
GenericPlugin
|
||||
GeneratedPlugin
|
||||
@plugin
|
||||
```
|
||||
|
||||
### `GeneratedPlugin` Customization
|
||||
|
||||
When you generate a plugin type with [`@plugin`](@ref), all required methods are
|
||||
implemented for you. However, you're still allowed to override behaviour if you so desire.
|
||||
These are the relevant methods:
|
||||
|
||||
```@docs
|
||||
source
|
||||
destination
|
||||
gitignore
|
||||
badges
|
||||
view
|
||||
```
|
||||
|
||||
For some examples, see
|
||||
[`generated.jl`](https://github.com/invenia/PkgTemplates.jl/tree/master/src/plugins/generated.jl).
|
||||
|
||||
## Custom Plugins
|
||||
|
||||
```@docs
|
||||
CustomPlugin
|
||||
```
|
||||
When a plugin is too complicated to be expressed with [`GeneratedPlugin`](@ref), we only
|
||||
need to implement a few methods to create something fully custom.
|
||||
|
||||
### `CustomPlugin` Required Methods
|
||||
|
||||
#### `gen_plugin`
|
||||
### Required Methods
|
||||
|
||||
```@docs
|
||||
gen_plugin
|
||||
```
|
||||
|
||||
### Optional Methods
|
||||
|
||||
```@docs
|
||||
interactive
|
||||
```
|
||||
|
||||
**Note**: [`interactive`](@ref) is not strictly required, however without it,
|
||||
your custom plugin will not be available when creating templates with
|
||||
[`interactive_template`](@ref).
|
||||
Additionally, [`gitignore`](@ref), [`badges`](@ref), and [`view`](@ref) can also be
|
||||
implemented in the same way as for [`GeneratedPlugin`](@ref)s (they have empty default
|
||||
implementations). [`source`](@ref) and [`destination`](@ref) have no meaning for custom
|
||||
plugins.
|
||||
|
||||
#### `badges`
|
||||
### Helpers
|
||||
|
||||
```@docs
|
||||
badges
|
||||
```
|
||||
|
||||
## Helper Types/Functions
|
||||
|
||||
#### `gen_file`
|
||||
|
||||
```@docs
|
||||
gen_file
|
||||
```
|
||||
|
||||
#### `substitute`
|
||||
|
||||
```@docs
|
||||
substitute
|
||||
```
|
||||
|
||||
#### `Badge`
|
||||
These types and functions will make implementing the above methods much easier.
|
||||
|
||||
```@docs
|
||||
Badge
|
||||
```
|
||||
|
||||
#### `format`
|
||||
|
||||
```@docs
|
||||
format
|
||||
```
|
||||
|
||||
#### `version_floor`
|
||||
|
||||
```@docs
|
||||
gen_file
|
||||
substitute
|
||||
version_floor
|
||||
```
|
||||
|
@ -28,6 +28,4 @@ Coveralls
|
||||
|
||||
```@docs
|
||||
Documenter
|
||||
GitHubPages
|
||||
GitLabPages
|
||||
```
|
||||
|
@ -1,36 +1,34 @@
|
||||
module PkgTemplates
|
||||
|
||||
using Dates
|
||||
using InteractiveUtils
|
||||
using LibGit2
|
||||
using Mustache
|
||||
using Pkg
|
||||
using REPL.TerminalMenus
|
||||
using URIParser
|
||||
using Base: @kwdef, current_project
|
||||
using Base.Filesystem: contractuser
|
||||
using Dates: month, today, year
|
||||
using InteractiveUtils: subtypes
|
||||
using LibGit2: LibGit2
|
||||
using Mustache: render
|
||||
using Pkg: PackageSpec, Pkg
|
||||
using REPL.TerminalMenus: MultiSelectMenu, RadioMenu, request
|
||||
using URIParser: URI
|
||||
|
||||
export
|
||||
# Template/package generation.
|
||||
Template,
|
||||
generate,
|
||||
interactive_template,
|
||||
generate_interactive,
|
||||
# Licenses.
|
||||
show_license,
|
||||
available_licenses,
|
||||
# Plugins.
|
||||
GitHubPages,
|
||||
GitLabPages,
|
||||
AppVeyor,
|
||||
TravisCI,
|
||||
GitLabCI,
|
||||
CirrusCI,
|
||||
Citation,
|
||||
Codecov,
|
||||
Coveralls,
|
||||
Citation
|
||||
Documenter,
|
||||
Gitignore,
|
||||
GitLabCI,
|
||||
License,
|
||||
Readme,
|
||||
Tests,
|
||||
TravisCI
|
||||
|
||||
const DEFAULT_VERSION = VersionNumber(VERSION.major)
|
||||
|
||||
"""
|
||||
A plugin to be added to a [`Template`](@ref), which adds some functionality or integration.
|
||||
New plugins should almost always extend [`GenericPlugin`](@ref) or [`CustomPlugin`](@ref).
|
||||
"""
|
||||
abstract type Plugin end
|
||||
|
||||
@ -38,18 +36,6 @@ include("licenses.jl")
|
||||
include("template.jl")
|
||||
include("generate.jl")
|
||||
include("plugin.jl")
|
||||
include(joinpath("plugins", "documenter.jl"))
|
||||
include(joinpath("plugins", "coveralls.jl"))
|
||||
include(joinpath("plugins", "appveyor.jl"))
|
||||
include(joinpath("plugins", "codecov.jl"))
|
||||
include(joinpath("plugins", "travisci.jl"))
|
||||
include(joinpath("plugins", "gitlabci.jl"))
|
||||
include(joinpath("plugins", "cirrusci.jl"))
|
||||
include(joinpath("plugins", "githubpages.jl"))
|
||||
include(joinpath("plugins", "gitlabpages.jl"))
|
||||
include(joinpath("plugins", "citation.jl"))
|
||||
|
||||
const DEFAULTS_DIR = normpath(joinpath(@__DIR__, "..", "defaults"))
|
||||
const BADGE_ORDER = [GitHubPages, GitLabPages, TravisCI, AppVeyor, GitLabCI, Codecov, Coveralls]
|
||||
include("interactive.jl")
|
||||
|
||||
end
|
||||
|
336
src/generate.jl
336
src/generate.jl
@ -1,16 +1,12 @@
|
||||
"""
|
||||
generate(pkg::AbstractString, t::Template) -> Nothing
|
||||
generate(t::Template, pkg::AbstractString) -> Nothing
|
||||
const TEST_UUID = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
|
||||
Generate a package named `pkg` from `t`. If `git` is `false`, no Git repository is created.
|
||||
"""
|
||||
function generate(
|
||||
pkg::AbstractString,
|
||||
t::Template;
|
||||
git::Bool=true,
|
||||
gitconfig::Union{GitConfig, Nothing}=nothing,
|
||||
)
|
||||
pkg = splitjl(pkg)
|
||||
(::Template)(pkg::AbstractString)
|
||||
|
||||
Generate a package named `pkg` from a [`Template`](@ref).
|
||||
"""
|
||||
function (t::Template)(pkg::AbstractString)
|
||||
endswith(pkg, ".jl") && (pkg = pkg[1:end-3])
|
||||
pkg_dir = joinpath(t.dir, pkg)
|
||||
ispath(pkg_dir) && throw(ArgumentError("$pkg_dir already exists"))
|
||||
|
||||
@ -18,9 +14,9 @@ function generate(
|
||||
# Create the directory with some boilerplate inside.
|
||||
Pkg.generate(pkg_dir)
|
||||
|
||||
# Add a [compat] section for Julia.
|
||||
# Add a [compat] section for Julia. By default, Julia 1.x is supported.
|
||||
open(joinpath(pkg_dir, "Project.toml"), "a") do io
|
||||
println(io, "\n[compat]\njulia = $(repr_version(t.julia_version))")
|
||||
println(io, "\n[compat]\njulia = \"1\"")
|
||||
end
|
||||
|
||||
# Replace the authors field with the template's authors.
|
||||
@ -31,329 +27,35 @@ function generate(
|
||||
write(path, replace(project, r"authors = .*" => "authors = $authors"))
|
||||
end
|
||||
|
||||
if git
|
||||
# Initialize the repo.
|
||||
if t.git
|
||||
# Initialize the repo, make a commit, and set the remote.
|
||||
repo = LibGit2.init(pkg_dir)
|
||||
@info "Initialized Git repo at $pkg_dir"
|
||||
|
||||
if gitconfig !== nothing
|
||||
# Configure the repo.
|
||||
repoconfig = GitConfig(repo)
|
||||
for c in LibGit2.GitConfigIter(gitconfig)
|
||||
LibGit2.set!(repoconfig, unsafe_string(c.name), unsafe_string(c.value))
|
||||
end
|
||||
end
|
||||
|
||||
# Commit and set the remote.
|
||||
LibGit2.commit(repo, "Initial commit")
|
||||
rmt = if t.ssh
|
||||
"git@$(t.host):$(t.user)/$pkg.jl.git"
|
||||
else
|
||||
"https://$(t.host)/$(t.user)/$pkg.jl"
|
||||
end
|
||||
# We need to set the remote in a strange way, see #8.
|
||||
close(LibGit2.GitRemote(repo, "origin", rmt))
|
||||
@info "Set remote origin to $rmt"
|
||||
|
||||
# Create the gh-pages branch if necessary.
|
||||
if haskey(t.plugins, GitHubPages)
|
||||
LibGit2.branch!(repo, "gh-pages")
|
||||
LibGit2.commit(repo, "Initial commit")
|
||||
@info "Created empty gh-pages branch"
|
||||
LibGit2.branch!(repo, "master")
|
||||
end
|
||||
end
|
||||
|
||||
# Generate the files.
|
||||
files = vcat(
|
||||
"src/", "Project.toml", # Created by Pkg.generate.
|
||||
gen_tests(pkg_dir, t),
|
||||
gen_readme(pkg_dir, t),
|
||||
gen_license(pkg_dir, t),
|
||||
vcat(map(p -> gen_plugin(p, t, pkg), values(t.plugins))...),
|
||||
)
|
||||
foreach(p -> gen_plugin(p, t, pkg_dir), values(t.plugins))
|
||||
|
||||
if git
|
||||
append!(files, gen_gitignore(pkg_dir, t))
|
||||
LibGit2.add!(repo, files...)
|
||||
if t.git
|
||||
# Commit the files.
|
||||
LibGit2.add!(repo, ".")
|
||||
LibGit2.commit(repo, "Files generated by PkgTemplates")
|
||||
@info "Committed $(length(files)) files/directories: $(join(files, ", "))"
|
||||
|
||||
|
||||
if length(collect(LibGit2.GitBranchIter(repo))) > 1
|
||||
@info "Remember to push all created branches to your remote: git push --all"
|
||||
end
|
||||
end
|
||||
|
||||
if t.dev
|
||||
# Add the new package to the current environment.
|
||||
Pkg.develop(PackageSpec(path=pkg_dir))
|
||||
Pkg.develop(PackageSpec(; path=pkg_dir))
|
||||
end
|
||||
|
||||
@info "New package is at $pkg_dir"
|
||||
catch e
|
||||
rm(pkg_dir; recursive=true)
|
||||
rethrow(e)
|
||||
catch
|
||||
rm(pkg_dir; recursive=true, force=true)
|
||||
rethrow()
|
||||
end
|
||||
end
|
||||
|
||||
function generate(
|
||||
t::Template,
|
||||
pkg::AbstractString;
|
||||
git::Bool=true,
|
||||
gitconfig::Union{GitConfig, Nothing}=nothing,
|
||||
)
|
||||
generate(pkg, t; git=git, gitconfig=gitconfig)
|
||||
end
|
||||
|
||||
"""
|
||||
generate_interactive(pkg::AbstractString; fast::Bool=false, git::Bool=true) -> Template
|
||||
|
||||
Interactively create a template, and then generate a package with it. Arguments and
|
||||
keywords are used in the same way as in [`generate`](@ref) and
|
||||
[`interactive_template`](@ref).
|
||||
"""
|
||||
function generate_interactive(
|
||||
pkg::AbstractString;
|
||||
fast::Bool=false,
|
||||
git::Bool=true,
|
||||
gitconfig::Union{GitConfig, Nothing}=nothing,
|
||||
)
|
||||
t = interactive_template(; git=git, fast=fast)
|
||||
generate(pkg, t; git=git, gitconfig=gitconfig)
|
||||
return t
|
||||
end
|
||||
|
||||
"""
|
||||
gen_tests(pkg_dir::AbstractString, t::Template) -> Vector{String}
|
||||
|
||||
Create the test entrypoint in `pkg_dir`.
|
||||
|
||||
# Arguments
|
||||
* `pkg_dir::AbstractString`: The package directory in which the files will be generated
|
||||
* `t::Template`: The template whose tests we are generating.
|
||||
|
||||
Returns an array of generated file/directory names.
|
||||
"""
|
||||
function gen_tests(pkg_dir::AbstractString, t::Template)
|
||||
# TODO: Silence Pkg for this section? Adding and removing Test creates a lot of noise.
|
||||
proj = Base.current_project()
|
||||
try
|
||||
Pkg.activate(pkg_dir)
|
||||
Pkg.add("Test")
|
||||
|
||||
# Move the Test dependency into the [extras] section.
|
||||
toml = read(joinpath(pkg_dir, "Project.toml"), String)
|
||||
lines = split(toml, "\n")
|
||||
idx = findfirst(l -> startswith(l, "Test = "), lines)
|
||||
testdep = lines[idx]
|
||||
deleteat!(lines, idx)
|
||||
toml = join(lines, "\n") * """
|
||||
[extras]
|
||||
$testdep
|
||||
|
||||
[targets]
|
||||
test = ["Test"]
|
||||
"""
|
||||
gen_file(joinpath(pkg_dir, "Project.toml"), toml)
|
||||
Pkg.update() # Regenerate Manifest.toml (this cleans up Project.toml too).
|
||||
finally
|
||||
proj === nothing ? Pkg.activate() : Pkg.activate(proj)
|
||||
end
|
||||
|
||||
pkg = basename(pkg_dir)
|
||||
text = """
|
||||
using $pkg
|
||||
using Test
|
||||
|
||||
@testset "$pkg.jl" begin
|
||||
# Write your own tests here.
|
||||
end
|
||||
"""
|
||||
|
||||
gen_file(joinpath(pkg_dir, "test", "runtests.jl"), text)
|
||||
return ["test/"]
|
||||
end
|
||||
|
||||
"""
|
||||
gen_readme(pkg_dir::AbstractString, t::Template) -> Vector{String}
|
||||
|
||||
Create a README in `pkg_dir` with badges for each enabled plugin.
|
||||
|
||||
# Arguments
|
||||
* `pkg_dir::AbstractString`: The directory in which the files will be generated.
|
||||
* `t::Template`: The template whose README we are generating.
|
||||
|
||||
Returns an array of generated file/directory names.
|
||||
"""
|
||||
function gen_readme(pkg_dir::AbstractString, t::Template)
|
||||
pkg = basename(pkg_dir)
|
||||
text = "# $pkg\n"
|
||||
done = []
|
||||
# Generate the ordered badges first, then add any remaining ones to the right.
|
||||
for plugin_type in BADGE_ORDER
|
||||
if haskey(t.plugins, plugin_type)
|
||||
text *= "\n"
|
||||
text *= join(
|
||||
badges(t.plugins[plugin_type], t.user, pkg),
|
||||
"\n",
|
||||
)
|
||||
push!(done, plugin_type)
|
||||
end
|
||||
end
|
||||
for plugin_type in setdiff(keys(t.plugins), done)
|
||||
text *= "\n"
|
||||
text *= join(
|
||||
badges(t.plugins[plugin_type], t.user, pkg),
|
||||
"\n",
|
||||
)
|
||||
end
|
||||
if haskey(t.plugins, Citation) && t.plugins[Citation].readme_section
|
||||
text *= "\n## Citing\n\nSee `CITATION.bib` for the relevant reference(s).\n"
|
||||
end
|
||||
|
||||
|
||||
gen_file(joinpath(pkg_dir, "README.md"), text)
|
||||
return ["README.md"]
|
||||
end
|
||||
|
||||
"""
|
||||
gen_gitignore(pkg_dir::AbstractString, t::Template) -> Vector{String}
|
||||
|
||||
Create a `.gitignore` in `pkg_dir`.
|
||||
|
||||
# Arguments
|
||||
* `pkg_dir::AbstractString`: The directory in which the files will be generated.
|
||||
* `t::Template`: The template whose .gitignore we are generating.
|
||||
|
||||
Returns an array of generated file/directory names.
|
||||
"""
|
||||
function gen_gitignore(pkg_dir::AbstractString, t::Template)
|
||||
pkg = basename(pkg_dir)
|
||||
init = [".DS_Store", "/dev/"]
|
||||
entries = mapfoldl(p -> p.gitignore, append!, values(t.plugins); init=init)
|
||||
if !t.manifest && !in("Manifest.toml", entries)
|
||||
push!(entries, "/Manifest.toml") # Only ignore manifests at the repo root.
|
||||
end
|
||||
unique!(sort!(entries))
|
||||
text = join(entries, "\n")
|
||||
|
||||
gen_file(joinpath(pkg_dir, ".gitignore"), text)
|
||||
files = [".gitignore"]
|
||||
t.manifest && push!(files, "Manifest.toml")
|
||||
return files
|
||||
end
|
||||
|
||||
"""
|
||||
gen_license(pkg_dir::AbstractString, t::Template) -> Vector{String}
|
||||
|
||||
Create a license in `pkg_dir`.
|
||||
|
||||
# Arguments
|
||||
* `pkg_dir::AbstractString`: The directory in which the files will be generated.
|
||||
* `t::Template`: The template whose LICENSE we are generating.
|
||||
|
||||
Returns an array of generated file/directory names.
|
||||
"""
|
||||
function gen_license(pkg_dir::AbstractString, t::Template)
|
||||
if isempty(t.license)
|
||||
return String[]
|
||||
end
|
||||
|
||||
text = "Copyright (c) $(year(today())) $(t.authors)\n"
|
||||
text *= read_license(t.license)
|
||||
|
||||
gen_file(joinpath(pkg_dir, "LICENSE"), text)
|
||||
return ["LICENSE"]
|
||||
end
|
||||
|
||||
"""
|
||||
gen_file(file::AbstractString, text::AbstractString) -> Int
|
||||
|
||||
Create a new file containing some given text. Always ends the file with a newline.
|
||||
|
||||
# Arguments
|
||||
* `file::AbstractString`: Path to the file to be created.
|
||||
* `text::AbstractString`: Text to write to the file.
|
||||
|
||||
Returns the number of bytes written to the file.
|
||||
"""
|
||||
function gen_file(file::AbstractString, text::AbstractString)
|
||||
mkpath(dirname(file))
|
||||
if !endswith(text , "\n")
|
||||
text *= "\n"
|
||||
end
|
||||
return write(file, text)
|
||||
end
|
||||
|
||||
"""
|
||||
version_floor(v::VersionNumber=VERSION) -> String
|
||||
|
||||
Format the given Julia version.
|
||||
|
||||
# Keyword arguments
|
||||
* `v::VersionNumber=VERSION`: Version to floor.
|
||||
|
||||
Returns "major.minor" for the most recent release version relative to v. For prereleases
|
||||
with v.minor == v.patch == 0, returns "major.minor-".
|
||||
"""
|
||||
function version_floor(v::VersionNumber=VERSION)
|
||||
return if isempty(v.prerelease) || v.patch > 0
|
||||
"$(v.major).$(v.minor)"
|
||||
else
|
||||
"$(v.major).$(v.minor)-"
|
||||
end
|
||||
end
|
||||
|
||||
"""
|
||||
substitute(template::AbstractString, view::Dict{String, Any}) -> String
|
||||
substitute(
|
||||
template::AbstractString,
|
||||
pkg_template::Template;
|
||||
view::Dict{String, Any}=Dict{String, Any}(),
|
||||
) -> String
|
||||
|
||||
Replace placeholders in `template` with values in `view` via
|
||||
[`Mustache`](https://github.com/jverzani/Mustache.jl). `template` is not modified.
|
||||
If `pkg_template` is supplied, some default replacements are also performed.
|
||||
|
||||
For information on how to structure `template`, see "Defining Template Files" section in
|
||||
[Custom Plugins](@ref).
|
||||
|
||||
**Note**: Conditionals in `template` without a corresponding key in `view` won't error,
|
||||
but will simply be evaluated as false.
|
||||
"""
|
||||
substitute(template::AbstractString, view::Dict{String, Any}) = render(template, view)
|
||||
|
||||
function substitute(
|
||||
template::AbstractString,
|
||||
pkg_template::Template;
|
||||
view::Dict{String, Any}=Dict{String, Any}(),
|
||||
)
|
||||
# Don't use version_floor here because we don't want the trailing '-' on prereleases.
|
||||
v = pkg_template.julia_version
|
||||
d = Dict{String, Any}(
|
||||
"USER" => pkg_template.user,
|
||||
"VERSION" => "$(v.major).$(v.minor)",
|
||||
"DOCUMENTER" => any(map(p -> isa(p, Documenter), values(pkg_template.plugins))),
|
||||
"CODECOV" => haskey(pkg_template.plugins, Codecov),
|
||||
"COVERALLS" => haskey(pkg_template.plugins, Coveralls),
|
||||
)
|
||||
# d["AFTER"] is true whenever something needs to occur in a CI "after_script".
|
||||
d["AFTER"] = d["DOCUMENTER"] || d["CODECOV"] || d["COVERALLS"]
|
||||
# d["COVERAGE"] is true whenever a coverage plugin is enabled.
|
||||
# TODO: This doesn't handle user-defined coverage plugins.
|
||||
# Maybe we need an abstract CoveragePlugin <: GenericPlugin?
|
||||
d["COVERAGE"] = d["CODECOV"] || d["COVERALLS"]
|
||||
return substitute(template, merge(d, view))
|
||||
end
|
||||
|
||||
splitjl(pkg::AbstractString) = endswith(pkg, ".jl") ? pkg[1:end-3] : pkg
|
||||
|
||||
# Format a version in a way suitable for a Project.toml file.
|
||||
function repr_version(v::VersionNumber)
|
||||
s = string(v.major)
|
||||
v.minor == 0 || (s *= ".$(v.minor)")
|
||||
v.patch == 0 || (s *= ".$(v.patch)")
|
||||
return repr(s)
|
||||
end
|
||||
|
152
src/interactive.jl
Normal file
152
src/interactive.jl
Normal file
@ -0,0 +1,152 @@
|
||||
# Printing utils.
|
||||
const TAB = repeat(' ', 4)
|
||||
const HALFTAB = repeat(' ', 2)
|
||||
const DOT = "• "
|
||||
const ARROW = "→ "
|
||||
const PLUGIN_TYPES = let
|
||||
leaves(T::Type) = isabstracttype(T) ? vcat(map(leaves, subtypes(T))...) : [T]
|
||||
leaves(Plugin)
|
||||
end
|
||||
|
||||
yesno(x::Bool) = x ? "Yes" : "No"
|
||||
|
||||
maybe_string(s::AbstractString) = isempty(s) ? "None" : string(s)
|
||||
|
||||
"""
|
||||
interactive(T::Type{<:Plugin}) -> T
|
||||
|
||||
Interactively create a plugin of type `T`.
|
||||
When this method is implemented for a type, it becomes available to [`Template`](@ref)s created with `interactive=true`.
|
||||
"""
|
||||
function interactive end
|
||||
|
||||
function make_template(::Val{true}; kwargs...)
|
||||
@info "Default values are shown in [brackets]"
|
||||
|
||||
opts = Dict{Symbol, Any}()
|
||||
fast = get(kwargs, :fast, false)
|
||||
|
||||
opts[:user] = get(kwargs, :user) do
|
||||
default = defaultkw(:user)
|
||||
default = isempty(default) ? nothing : default
|
||||
prompt_string("Username", default)
|
||||
end
|
||||
|
||||
git = opts[:git] = get(kwargs, :git) do
|
||||
default = defaultkw(:git)
|
||||
fast ? default : prompt_bool("Create Git repositories for packages", default)
|
||||
end
|
||||
|
||||
opts[:host] = get(kwargs, :host) do
|
||||
default = defaultkw(:host)
|
||||
if fast || !git
|
||||
default
|
||||
else
|
||||
prompt_string("Code hosting service", default)
|
||||
end
|
||||
end
|
||||
|
||||
opts[:license] = get(kwargs, :license) do
|
||||
default = defaultkw(:license)
|
||||
if fast
|
||||
default
|
||||
else
|
||||
# TODO: Break this out into something reusable?
|
||||
choices = String["None"; split(sprint(available_licenses), "\n")]
|
||||
licenses = ["" => "", pairs(LICENSES)...]
|
||||
menu = RadioMenu(choices)
|
||||
first(licenses[request("License:", menu)])
|
||||
end
|
||||
end
|
||||
|
||||
opts[:authors] = get(kwargs, :authors) do
|
||||
default = defaultkw(:authors)
|
||||
if fast || !git
|
||||
default
|
||||
else
|
||||
prompt_string("Package author(s)", isempty(default) ? "None" : default)
|
||||
end
|
||||
end
|
||||
|
||||
opts[:dir] = get(kwargs, :dir) do
|
||||
default = defaultkw(:dir)
|
||||
fast ? default : prompt_string("Path to package directory", default)
|
||||
end
|
||||
|
||||
opts[:julia_version] = get(kwargs, :julia_version) do
|
||||
default = defaultkw(:julia_version)
|
||||
if fast
|
||||
default
|
||||
else
|
||||
VersionNumber(prompt_string("Minimum Julia version", string(default)))
|
||||
end
|
||||
end
|
||||
|
||||
opts[:ssh] = get(kwargs, :ssh) do
|
||||
default = defaultkw(:ssh)
|
||||
fast || !git ? default : prompt_bool("Set remote to SSH", default)
|
||||
end
|
||||
|
||||
opts[:manifest] = get(kwargs, :manifest) do
|
||||
default = defaultkw(:manifest)
|
||||
fast || !git ? default : prompt_bool("Commit Manifest.toml", default)
|
||||
end
|
||||
|
||||
opts[:develop] = get(kwargs, :develop) do
|
||||
default = defaultkw(:develop)
|
||||
fast || !git ? default : prompt_bool("Develop generated packages", default)
|
||||
end
|
||||
|
||||
opts[:plugins] = get(kwargs, :plugins) do
|
||||
# TODO: Break this out into something reusable?
|
||||
types = filter(T -> applicable(interactive, T), PLUGIN_TYPES)
|
||||
menu = MultiSelectMenu(map(string ∘ nameof, types))
|
||||
selected = types[collect(request("Plugins:", menu))]
|
||||
map(interactive, selected)
|
||||
end
|
||||
|
||||
return make_template(Val(false); opts...)
|
||||
end
|
||||
|
||||
prompt_string(s::AbstractString, default=nothing) = prompt(string, s, default)
|
||||
|
||||
function prompt_bool(s::AbstractString, default=nothing)
|
||||
return prompt(s, default) do answer
|
||||
answer = lowercase(answer)
|
||||
if answer in ["yes", "true", "y", "t"]
|
||||
true
|
||||
elseif answer in ["no", "false", "n", "f"]
|
||||
false
|
||||
else
|
||||
throw(ArgumentError("Invalid yes/no response"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function prompt(f::Function, s::AbstractString, default)
|
||||
required = default === nothing
|
||||
default_display = default isa Bool ? yesno(default) : default
|
||||
print(s, " [", required ? "REQUIRED" : default_display, "]: ")
|
||||
answer = readline()
|
||||
return if isempty(answer)
|
||||
required && throw(ArgumentError("This argument is required"))
|
||||
default
|
||||
else
|
||||
f(answer)
|
||||
end
|
||||
end
|
||||
|
||||
function prompt_config(T::Type{<:BasicPlugin})
|
||||
s = "$(nameof(T)): Source file template path"
|
||||
default = source(T)
|
||||
default === nothing && (s *= " (\"None\" for no file)")
|
||||
answer = prompt_string(s, default === nothing ? "None" : contractuser(default))
|
||||
|
||||
return if lowercase(answer) == "none"
|
||||
nothing
|
||||
elseif isempty(answer)
|
||||
default
|
||||
else
|
||||
answer
|
||||
end
|
||||
end
|
@ -1,45 +0,0 @@
|
||||
const LICENSE_DIR = normpath(joinpath(@__DIR__, "..", "licenses"))
|
||||
const LICENSES = Dict(
|
||||
"MIT" => "MIT \"Expat\" License",
|
||||
"BSD2" => "Simplified \"2-clause\" BSD License",
|
||||
"BSD3" => "Modified \"3-clause\" BSD License",
|
||||
"ISC" => "Internet Systems Consortium License",
|
||||
"ASL" => "Apache License, Version 2.0",
|
||||
"MPL" => "Mozilla Public License, Version 2.0",
|
||||
"GPL-2.0+" => "GNU Public License, Version 2.0+",
|
||||
"GPL-3.0+" => "GNU Public License, Version 3.0+",
|
||||
"LGPL-2.1+" => "Lesser GNU Public License, Version 2.1+",
|
||||
"LGPL-3.0+" => "Lesser GNU Public License, Version 3.0+",
|
||||
"EUPL-1.2+" => "European Union Public Licence, Version 1.2+",
|
||||
)
|
||||
|
||||
"""
|
||||
available_licenses([io::IO]) -> Nothing
|
||||
|
||||
Print the names of all available licenses.
|
||||
"""
|
||||
available_licenses(io::IO) = print(io, join(("$k: $v" for (k, v) in LICENSES), "\n"))
|
||||
available_licenses() = available_licenses(stdout)
|
||||
|
||||
"""
|
||||
show_license([io::IO], license::AbstractString) -> Nothing
|
||||
|
||||
Print the text of `license`. Errors if the license is not found.
|
||||
"""
|
||||
show_license(io::IO, license::AbstractString) = print(io, read_license(license))
|
||||
show_license(license::AbstractString) = show_license(stdout, license)
|
||||
|
||||
"""
|
||||
read_license(license::AbstractString) -> String
|
||||
|
||||
Returns the contents of `license`. Errors if the license is not found. Use
|
||||
[`available_licenses`](@ref) to view available licenses.
|
||||
"""
|
||||
function read_license(license::AbstractString)
|
||||
path = joinpath(LICENSE_DIR, license)
|
||||
if isfile(path)
|
||||
return string(readchomp(path))
|
||||
else
|
||||
throw(ArgumentError("License '$license' is not available"))
|
||||
end
|
||||
end
|
289
src/plugin.jl
289
src/plugin.jl
@ -1,153 +1,51 @@
|
||||
"""
|
||||
Generic plugins are plugins that add any number of patterns to the generated package's
|
||||
`.gitignore`, and have at most one associated file to generate.
|
||||
const DEFAULTS_DIR = normpath(joinpath(@__DIR__, "..", "defaults"))
|
||||
|
||||
# Attributes
|
||||
* `gitignore::Vector{AbstractString}`: Array of patterns to be added to the `.gitignore` of
|
||||
generated packages that use this plugin.
|
||||
* `src::Union{AbstractString, Nothing}`: Path to the file that will be copied into the generated
|
||||
package repository. If set to `nothing`, no file will be generated. When this defaults
|
||||
to an empty string, there should be a default file in `defaults` that will be copied.
|
||||
That file's name is usually the same as the plugin's name, except in all lowercase and
|
||||
with the `.yml` extension. If this is not the case, an `interactive` method needs to be
|
||||
implemented to call `interactive(; file="file.ext")`.
|
||||
* `dest::AbstractString`: Path to the generated file, relative to the root of the generated
|
||||
package repository.
|
||||
* `badges::Vector{Badge}`: Array of [`Badge`](@ref)s containing information used to
|
||||
create Markdown-formatted badges from the plugin. Entries will be run through
|
||||
[`substitute`](@ref), so they may contain placeholder values.
|
||||
* `view::Dict{String, Any}`: Additional substitutions to make in both the plugin's badges
|
||||
and its associated file. See [`substitute`](@ref) for details.
|
||||
abstract type BasicPlugin <: Plugin end
|
||||
|
||||
# Example
|
||||
```julia
|
||||
struct MyPlugin <: GenericPlugin
|
||||
gitignore::Vector{AbstractString}
|
||||
src::Union{AbstractString, Nothing}
|
||||
dest::AbstractString
|
||||
badges::Vector{Badge}
|
||||
view::Dict{String, Any}
|
||||
|
||||
function MyPlugin(; config_file::Union{AbstractString, Nothing}="")
|
||||
if config_file != nothing
|
||||
config_file = if isempty(config_file)
|
||||
joinpath(DEFAULTS_DIR, "my-plugin.toml")
|
||||
elseif isfile(config_file)
|
||||
abspath(config_file)
|
||||
else
|
||||
throw(ArgumentError(
|
||||
"File \$(abspath(config_file)) does not exist"
|
||||
))
|
||||
end
|
||||
end
|
||||
new(
|
||||
["*.mgp"],
|
||||
config_file,
|
||||
".my-plugin.toml",
|
||||
[
|
||||
Badge(
|
||||
"My Plugin",
|
||||
"https://myplugin.com/badge-{{YEAR}}.png",
|
||||
"https://myplugin.com/{{USER}}/{{PKGNAME}}.jl",
|
||||
),
|
||||
],
|
||||
Dict{String, Any}("YEAR" => year(today())),
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
interactive(::Type{MyPlugin}) = interactive(MyPlugin; file="my-plugin.toml")
|
||||
```
|
||||
|
||||
The above plugin ignores files ending with `.mgp`, copies `defaults/my-plugin.toml` by
|
||||
default, and creates a badge that links to the project on its own site, using the default
|
||||
substitutions with one addition: `{{YEAR}} => year(today())`. Since the default config
|
||||
template file doesn't follow the generic naming convention, we added another `interactive`
|
||||
method to correct the assumed filename.
|
||||
"""
|
||||
abstract type GenericPlugin <: Plugin end
|
||||
|
||||
function Base.show(io::IO, p::GenericPlugin)
|
||||
spc = " "
|
||||
println(io, nameof(typeof(p)), ":")
|
||||
|
||||
cfg = if p.src === nothing
|
||||
"None"
|
||||
else
|
||||
dirname(p.src) == DEFAULTS_DIR ? "Default" : p.src
|
||||
end
|
||||
println(io, spc, "→ Config file: ", cfg)
|
||||
|
||||
n = length(p.gitignore)
|
||||
s = n == 1 ? "" : "s"
|
||||
print(io, spc, "→ $n gitignore entrie$s")
|
||||
n > 0 && print(io, ": ", join(map(repr, p.gitignore), ", "))
|
||||
end
|
||||
default_file(paths::AbstractString...) = joinpath(DEFAULTS_DIR, paths...)
|
||||
|
||||
"""
|
||||
Custom plugins are plugins whose behaviour does not follow the [`GenericPlugin`](@ref)
|
||||
pattern. They can implement [`gen_plugin`](@ref), [`badges`](@ref), and
|
||||
[`interactive`](@ref) in any way they choose, as long as they conform to the usual type
|
||||
signature.
|
||||
view(::Plugin, ::Template, pkg::AbstractString) -> Dict{String}
|
||||
|
||||
# Attributes
|
||||
* `gitignore::Vector{AbstractString}`: Array of patterns to be added to the `.gitignore` of
|
||||
generated packages that use this plugin.
|
||||
|
||||
# Example
|
||||
```julia
|
||||
struct MyPlugin <: CustomPlugin
|
||||
gitignore::Vector{AbstractString}
|
||||
lucky::Bool
|
||||
|
||||
MyPlugin() = new([], rand() > 0.8)
|
||||
|
||||
function gen_plugin(p::MyPlugin, t::Template, pkg_name::AbstractString)
|
||||
return if p.lucky
|
||||
text = substitute("You got lucky with {{PKGNAME}}, {{USER}}!", t)
|
||||
gen_file(joinpath(t.dir, pkg_name, ".myplugin.yml"), text)
|
||||
[".myplugin.yml"]
|
||||
else
|
||||
println("Maybe next time.")
|
||||
String[]
|
||||
end
|
||||
end
|
||||
|
||||
function badges(p::MyPlugin, user::AbstractString, pkg_name::AbstractString)
|
||||
return if p.lucky
|
||||
[
|
||||
format(Badge(
|
||||
"You got lucky!",
|
||||
"https://myplugin.com/badge.png",
|
||||
"https://myplugin.com/\$user/\$pkg_name.jl",
|
||||
)),
|
||||
]
|
||||
else
|
||||
String[]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
interactive(:Type{MyPlugin}) = MyPlugin()
|
||||
```
|
||||
|
||||
This plugin doesn't do much, but it demonstrates how [`gen_plugin`](@ref), [`badges`](@ref)
|
||||
and [`interactive`](@ref) can be implemented using [`substitute`](@ref),
|
||||
[`gen_file`](@ref), [`Badge`](@ref), and [`format`](@ref).
|
||||
|
||||
# Defining Template Files
|
||||
Often, the contents of the config file that your plugin generates depends on variables like
|
||||
the package name, the user's username, etc. Template files (which are stored in `defaults`)
|
||||
can use [here](https://github.com/jverzani/Mustache.jl)'s syntax to define replacements.
|
||||
Return extra string substitutions to be made for this plugin.
|
||||
"""
|
||||
abstract type CustomPlugin <: Plugin end
|
||||
view(::Plugin, ::Template, ::AbstractString) = Dict{String, Any}()
|
||||
|
||||
"""
|
||||
gitignore(::Plugin) -> Vector{String}
|
||||
|
||||
Return patterns that should be added to `.gitignore`.
|
||||
"""
|
||||
gitignore(::Plugin) = String[]
|
||||
|
||||
"""
|
||||
badges(::Plugin) -> Union{Badge, Vector{Badge}}
|
||||
|
||||
Return a list of [`Badge`](@ref)s, or just one, to be added to `README.md`.
|
||||
"""
|
||||
badges(::Plugin) = Badge[]
|
||||
|
||||
"""
|
||||
source(::BasicPlugin) -> Union{String, Nothing}
|
||||
|
||||
Return the path to a plugin's configuration file template, or `nothing` to indicate no file.
|
||||
"""
|
||||
source(::BasicPlugin) = nothing
|
||||
|
||||
"""
|
||||
destination(::BasicPlugin) -> String
|
||||
|
||||
Return the destination, relative to the package root, of a plugin's configuration file.
|
||||
"""
|
||||
function destination end
|
||||
|
||||
"""
|
||||
Badge(hover::AbstractString, image::AbstractString, link::AbstractString) -> Badge
|
||||
|
||||
A `Badge` contains the data necessary to generate a Markdown badge.
|
||||
Container for Markdown badge data.
|
||||
Each argument can contain placeholders.
|
||||
|
||||
# Arguments
|
||||
## Arguments
|
||||
* `hover::AbstractString`: Text to appear when the mouse is hovered over the badge.
|
||||
* `image::AbstractString`: URL to the image to display.
|
||||
* `link::AbstractString`: URL to go to upon clicking the badge.
|
||||
@ -158,89 +56,70 @@ struct Badge
|
||||
link::String
|
||||
end
|
||||
|
||||
"""
|
||||
format(b::Badge) -> String
|
||||
Base.string(b::Badge) = "[)]($(b.link))"
|
||||
|
||||
Return `badge`'s data formatted as a Markdown string.
|
||||
"""
|
||||
format(b::Badge) = "[)]($(b.link))"
|
||||
# Format a plugin's badges as a list of strings, with all substitutions applied.
|
||||
function badges(p::Plugin, t::Template, pkg_name::AbstractString)
|
||||
bs = badges(p)
|
||||
bs isa Vector || (bs = [bs])
|
||||
bs = map(string, bs)
|
||||
# TODO render
|
||||
end
|
||||
|
||||
"""
|
||||
gen_plugin(p::Plugin, t::Template, pkg_name::AbstractString) -> Vector{String}
|
||||
gen_plugin(p::Plugin, t::Template, pkg::AbstractString) -> Nothing
|
||||
|
||||
Generate any files associated with a plugin.
|
||||
|
||||
# Arguments
|
||||
## Arguments
|
||||
* `p::Plugin`: Plugin whose files are being generated.
|
||||
* `t::Template`: Template configuration.
|
||||
* `pkg_name::AbstractString`: Name of the package.
|
||||
|
||||
Returns an array of generated file/directory names.
|
||||
* `pkg::AbstractString`: Name of the package.
|
||||
"""
|
||||
gen_plugin(::Plugin, ::Template, ::AbstractString) = String[]
|
||||
gen_plugin(::Plugin, ::Template, ::AbstractString) = nothing
|
||||
|
||||
function gen_plugin(p::GenericPlugin, t::Template, pkg_name::AbstractString)
|
||||
if p.src === nothing
|
||||
return String[]
|
||||
end
|
||||
text = substitute(
|
||||
read(p.src, String),
|
||||
t;
|
||||
view=merge(Dict("PKGNAME" => pkg_name), p.view),
|
||||
)
|
||||
gen_file(joinpath(t.dir, pkg_name, p.dest), text)
|
||||
return [p.dest]
|
||||
function gen_plugin(p::BasicPlugin, t::Template, pkg::AbstractString)
|
||||
source(p) === nothing && return
|
||||
text = render(source(p), view(p, t, pkg); tags=tags(p))
|
||||
gen_file(joinpath(t.dir, pkg_name, destination(p)), text)
|
||||
end
|
||||
|
||||
"""
|
||||
badges(p::Plugin, user::AbstractString, pkg_name::AbstractString) -> Vector{String}
|
||||
gen_file(file::AbstractString, text::AbstractString) -> Int
|
||||
|
||||
Generate Markdown badges for the plugin.
|
||||
|
||||
# Arguments
|
||||
* `p::Plugin`: Plugin whose badges we are generating.
|
||||
* `user::AbstractString`: Username of the package creator.
|
||||
* `pkg_name::AbstractString`: Name of the package.
|
||||
|
||||
Returns an array of Markdown badges.
|
||||
Create a new file containing some given text.
|
||||
Trailing whitespace is removed, and the file will end with a newline.
|
||||
"""
|
||||
badges(::Plugin, ::AbstractString, ::AbstractString) = String[]
|
||||
|
||||
function badges(p::GenericPlugin, user::AbstractString, pkg_name::AbstractString)
|
||||
# Give higher priority to replacements defined in the plugin's view.
|
||||
view = merge(Dict("USER" => user, "PKGNAME" => pkg_name), p.view)
|
||||
return map(b -> substitute(format(b), view), p.badges)
|
||||
function gen_file(file::AbstractString, text::AbstractString)
|
||||
mkpath(dirname(file))
|
||||
text = join(map(rstrip, split(text, "\n")), "\n")
|
||||
endswith(text , "\n") || (text *= "\n")
|
||||
write(file, text)
|
||||
end
|
||||
|
||||
"""
|
||||
interactive(T::Type{<:Plugin}; file::Union{AbstractString, Nothing}="") -> Plugin
|
||||
render_file(file::AbstractString, view, tags) = render_text(read(file, String), view, tags)
|
||||
|
||||
Interactively create a plugin of type `T`, where `file` is the plugin type's default
|
||||
config template with a non-standard name (for `MyPlugin`, this is anything but
|
||||
"myplugin.yml").
|
||||
"""
|
||||
function interactive(T::Type{<:GenericPlugin}; file::Union{AbstractString, Nothing}="")
|
||||
name = string(nameof(T))
|
||||
# By default, we expect the default plugin file template for a plugin called
|
||||
# "MyPlugin" to be called "myplugin.yml".
|
||||
fn = file != nothing && isempty(file) ? "$(lowercase(name)).yml" : file
|
||||
default_config_file = fn == nothing ? fn : joinpath(DEFAULTS_DIR, fn)
|
||||
render_text(text::AbstractString, view, tags) = render(text, view; tags=tags)
|
||||
|
||||
print("$name: Enter the config template filename (\"None\" for no file) ")
|
||||
if default_config_file == nothing
|
||||
print("[None]: ")
|
||||
else
|
||||
print("[", replace(default_config_file, homedir() => "~"), "]: ")
|
||||
end
|
||||
|
||||
config_file = readline()
|
||||
config_file = if uppercase(config_file) == "NONE"
|
||||
nothing
|
||||
elseif isempty(config_file)
|
||||
default_config_file
|
||||
else
|
||||
config_file
|
||||
end
|
||||
|
||||
return T(; config_file=config_file)
|
||||
function render_badges(p::BasicPlugin, t::Template, pkg::AbstractString)
|
||||
end
|
||||
|
||||
function render_plugin(p::BasicPlugin, t::Template, pkg::AbstractString)
|
||||
render_file(source(p), view(p, t, pkg), tags(p))
|
||||
end
|
||||
|
||||
include(joinpath("plugins", "essentials.jl"))
|
||||
include(joinpath("plugins", "coverage.jl"))
|
||||
include(joinpath("plugins", "ci.jl"))
|
||||
include(joinpath("plugins", "citation.jl"))
|
||||
include(joinpath("plugins", "documenter.jl"))
|
||||
|
||||
const BADGE_ORDER = [
|
||||
Documenter{GitLabCI},
|
||||
Documenter{TravisCI},
|
||||
TravisCI,
|
||||
AppVeyor,
|
||||
GitLabCI,
|
||||
Codecov,
|
||||
Coveralls,
|
||||
]
|
||||
|
@ -1,42 +0,0 @@
|
||||
"""
|
||||
AppVeyor(; config_file::Union{AbstractString, Nothing}="") -> AppVeyor
|
||||
|
||||
Add `AppVeyor` to a template's plugins to add a `.appveyor.yml` configuration file to
|
||||
generated repositories, and an appropriate badge to the README.
|
||||
|
||||
# Keyword Arguments
|
||||
* `config_file::Union{AbstractString, Nothing}=""`: Path to a custom `.appveyor.yml`.
|
||||
If `nothing` is supplied, no file will be generated.
|
||||
"""
|
||||
struct AppVeyor <: GenericPlugin
|
||||
gitignore::Vector{String}
|
||||
src::Union{String, Nothing}
|
||||
dest::String
|
||||
badges::Vector{Badge}
|
||||
view::Dict{String, Any}
|
||||
|
||||
function AppVeyor(; config_file::Union{AbstractString, Nothing}="")
|
||||
if config_file != nothing
|
||||
config_file = if isempty(config_file)
|
||||
config_file = joinpath(DEFAULTS_DIR, "appveyor.yml")
|
||||
elseif isfile(config_file)
|
||||
abspath(config_file)
|
||||
else
|
||||
throw(ArgumentError("File $(abspath(config_file)) does not exist"))
|
||||
end
|
||||
end
|
||||
new(
|
||||
[],
|
||||
config_file,
|
||||
".appveyor.yml",
|
||||
[
|
||||
Badge(
|
||||
"Build Status",
|
||||
"https://ci.appveyor.com/api/projects/status/github/{{USER}}/{{PKGNAME}}.jl?svg=true",
|
||||
"https://ci.appveyor.com/project/{{USER}}/{{PKGNAME}}-jl",
|
||||
)
|
||||
],
|
||||
Dict{String, Any}(),
|
||||
)
|
||||
end
|
||||
end
|
140
src/plugins/ci.jl
Normal file
140
src/plugins/ci.jl
Normal file
@ -0,0 +1,140 @@
|
||||
const DEFAULT_CI_VERSIONS = ["1.0", "nightly"]
|
||||
const VersionsOrStrings = Vector{Union{VersionNumber, String}}
|
||||
|
||||
format_version(v::VersionNumber) = "$(v.major).$(v.minor)"
|
||||
|
||||
function collect_versions(versions::Vector, t::Template)
|
||||
return unique(sort([versions; format_version(t.julia_version)]; by=string))
|
||||
end
|
||||
|
||||
abstract type CI <: Plugin end
|
||||
|
||||
@kwdef struct TravisCI <: CI
|
||||
file::String = default_file("travis.yml")
|
||||
linux::Bool = true
|
||||
osx::Bool = true
|
||||
windows::Bool = true
|
||||
x86::Bool = false
|
||||
coverage::Bool = true
|
||||
extra_versions::VersionsOrStrings = DEFAULT_CI_VERSIONS
|
||||
end
|
||||
|
||||
source(p::TravisCI) = p.file
|
||||
destination(::TravisCI) = ".travis.yml"
|
||||
|
||||
badges(::TravisCI) = Badge(
|
||||
"Build Status",
|
||||
"https://travis-ci.com/{{USER}}/{{PKG}}.jl.svg?branch=master",
|
||||
"https://travis-ci.com/{{USER}}/{{PKG}}.jl",
|
||||
)
|
||||
|
||||
function view(p::TravisCI, t::Template, ::AbstractString)
|
||||
jobs = Dict{String, String}[]
|
||||
for v in collect_versions(p.extra_versions, t)
|
||||
p.linux && push!(jobs, Dict("JULIA" => v, "OS" => "linux", "ARCH" => "x64"))
|
||||
p.linux && p.x86 && push!(jobs, Dict("JULIA" => v, "OS" => "linux", "ARCH" => "x86"))
|
||||
p.osx && push!(jobs, Dict("JULIA" => v, "OS" => "osx"))
|
||||
p.windows && push!(jobs, Dict("JULIA" => v, "OS" => "windows", "ARCH" => "x64"))
|
||||
p.windows && p.x86 && push!(jobs, Dict("JULIA" => v, "OS" => "windows", "ARCH" => "x86"))
|
||||
end
|
||||
return Dict(
|
||||
"HAS_CODECOV" => hasplugin(t, Codecov),
|
||||
"HAS_COVERAGE" => p.coverage && hasplugin(t, Coverage),
|
||||
"HAS_COVERALLS" => hasplugin(t, Coveralls),
|
||||
"HAS_DOCUMENTER" => hasplugin(t, Documenter{TravisCI}),
|
||||
"HAS_NIGHTLY" => "nightly" in versions,
|
||||
"PKG" => pkg,
|
||||
"VERSION" => format_version(t.julia_version),
|
||||
)
|
||||
end
|
||||
|
||||
@kwdef struct AppVeyor <: CI
|
||||
file::String = default_file("appveyor.yml")
|
||||
x86::Bool = false
|
||||
coverage::Bool = true
|
||||
extra_versions::VersionsOrStrings = DEFAULT_CI_VERSIONS
|
||||
end
|
||||
|
||||
source(p::AppVeyor) = p.file
|
||||
destination(::AppVeyor) = ".appveyor.yml"
|
||||
|
||||
badges(::AppVeyor) = Badge(
|
||||
"Build Status",
|
||||
"https://ci.appveyor.com/api/projects/status/github/{{USER}}/{{PKG}}.jl?svg=true",
|
||||
"https://ci.appveyor.com/project/{{USER}}/{{PKG}}-jl",
|
||||
)
|
||||
|
||||
function view(p::AppVeyor, t::Template, ::AbstractString)
|
||||
platforms = ["x64"]
|
||||
t.x86 && push!(platforms, "x86")
|
||||
return Dict(
|
||||
"HAS_CODECOV" => t.coverage && hasplugin(t, Codecov),
|
||||
"HAS_NIGHTLY" => "nightly" in versions,
|
||||
"PKG" => pkg,
|
||||
"PLATFORMS" => os,
|
||||
"VERSIONS" => collect_versions(p.extra_versions, t),
|
||||
)
|
||||
end
|
||||
|
||||
@kwdef struct CirrusCI <: CI
|
||||
file::String = default_file("cirrus.yml")
|
||||
image::String = "freebsd-12-0-release-amd64"
|
||||
coverage::Bool = true
|
||||
extra_versions::VersionsOrStrings = DEFAULT_CI_VERSIONS
|
||||
end
|
||||
|
||||
source(p::CirrusCI) = p.file
|
||||
destination(::CirrusCI) = ".cirrus.yml"
|
||||
|
||||
badges(::CirrusCI) = Badge(
|
||||
"Build Status",
|
||||
"https://api.cirrus-ci.com/github/{{USER}}/{{PACKAGE}}.jl.svg",
|
||||
"https://cirrus-ci.com/github/{{USER}}/{{PKG}}.jl",
|
||||
)
|
||||
|
||||
function view(p::CirrusCI, t::Template, ::AbstractString)
|
||||
return Dict(
|
||||
"HAS_CODECOV" => hasplugin(t, Codecov),
|
||||
"HAS_COVERALLS" => hasplugin(t, Coveralls),
|
||||
"HAS_COVERAGE" => p.coverage && hasplugin(t, Coverage),
|
||||
"IMAGE" => p.image,
|
||||
"PKG" => pkg,
|
||||
"VERSIONS" => collect_versions(p.extra_versions, t),
|
||||
)
|
||||
end
|
||||
|
||||
@kwdef struct GitLabCI <: CI
|
||||
file::String
|
||||
documentation::Bool = true
|
||||
coverage::Bool = true
|
||||
extra_versions::Vector{VersionNumber} = [v"1.0"]
|
||||
end
|
||||
|
||||
gitignore(p::GitLabCI) = p.coverage ? COVERAGE_GITIGNORE : String[]
|
||||
|
||||
source(p::GitLabCI) = p.source
|
||||
destination(::GitLabCI) = ".gitlab-ci.yml"
|
||||
|
||||
function badges(p::GitLabCI)
|
||||
ci = Badge(
|
||||
"Build Status",
|
||||
"https://gitlab.com/{{USER}}/{{PKG}}.jl/badges/master/build.svg",
|
||||
"https://gitlab.com/{{USER}}/{{PKG}}.jl/pipelines",
|
||||
)
|
||||
cov = Badge(
|
||||
"Coverage",
|
||||
"https://gitlab.com/{{USER}}/{{PKG}}.jl/badges/master/coverage.svg",
|
||||
"https://gitlab.com/{{USER}}/{{PKG}}.jl/commits/master",
|
||||
)
|
||||
return p.coverage ? [ci, cov] : [ci]
|
||||
end
|
||||
|
||||
function view(p::GitLabCI, t::Template, ::AbstractString)
|
||||
return Dict(
|
||||
"HAS_COVERAGE" => p.coverage,
|
||||
"HAS_DOCUMENTER" => hasplugin(t, Documenter{GitLabCI}),
|
||||
"PKG" => pkg,
|
||||
"VERSION" => format_version(t.julia_version),
|
||||
"VERSIONS" => collect_versions(p.extra_versions, t),
|
||||
)
|
||||
end
|
@ -1,45 +0,0 @@
|
||||
"""
|
||||
CirrusCI(; config_file::Union{AbstractString, Nothing}="") -> CirrusCI
|
||||
|
||||
Add `CirrusCI` to a template's plugins to add a `.cirrus.yml` configuration file to
|
||||
generated repositories, and an appropriate badge to the README. The default configuration
|
||||
file supports only FreeBSD builds via [CirrusCI.jl](https://github.com/ararslan/CirrusCI.jl)
|
||||
|
||||
# Keyword Arguments
|
||||
* `config_file::Union{AbstractString, Nothing}=""`: Path to a custom `.cirrus.yml`.
|
||||
If `nothing` is supplied, no file will be generated.
|
||||
"""
|
||||
struct CirrusCI <: GenericPlugin
|
||||
gitignore::Vector{String}
|
||||
src::Union{String, Nothing}
|
||||
dest::String
|
||||
badges::Vector{Badge}
|
||||
view::Dict{String, Any}
|
||||
|
||||
function CirrusCI(; config_file::Union{AbstractString, Nothing}="")
|
||||
if config_file !== nothing
|
||||
config_file = if isempty(config_file)
|
||||
joinpath(DEFAULTS_DIR, "cirrus.yml")
|
||||
elseif isfile(config_file)
|
||||
abspath(config_file)
|
||||
else
|
||||
throw(ArgumentError("File $(abspath(config_file)) does not exist"))
|
||||
end
|
||||
end
|
||||
return new(
|
||||
[],
|
||||
config_file,
|
||||
".cirrus.yml",
|
||||
[
|
||||
Badge(
|
||||
"Build Status",
|
||||
"https://api.cirrus-ci.com/github/{{USER}}/{{PKGNAME}}.jl.svg",
|
||||
"https://cirrus-ci.com/github/{{USER}}/{{PKGNAME}}.jl",
|
||||
),
|
||||
],
|
||||
Dict{String, Any}(),
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
interactive(::Type{CirrusCI}) = interactive(CirrusCI; file="cirrus.yml")
|
@ -1,50 +1,28 @@
|
||||
"""
|
||||
Citation(; readme_section::Bool=false)
|
||||
Citation(; readme_section::Bool=false) -> Citation
|
||||
|
||||
Add `Citation` to a template's plugins to add a `CITATION.bib` file to
|
||||
generated repositories, and an appropriate section in the README.
|
||||
|
||||
# Keyword Arguments:
|
||||
* `readme_section::Bool=false`: whether to add a section in the readme pointing to `CITATION.bib`.
|
||||
Add `Citation` to a [`Template`](@ref)'s plugin list to generate a `CITATION.bib` file.
|
||||
If `readme` is set, then `README.md` will contain a section about citing.
|
||||
"""
|
||||
struct Citation <: GenericPlugin
|
||||
gitignore::Vector{AbstractString}
|
||||
src::Union{String, Nothing}
|
||||
dest::AbstractString
|
||||
badges::Vector{Badge}
|
||||
view::Dict{String, Any}
|
||||
readme_section::Bool
|
||||
function Citation(; readme_section::Bool=false)
|
||||
new(
|
||||
[],
|
||||
nothing,
|
||||
"CITATION.bib",
|
||||
[],
|
||||
Dict{String, Any}(),
|
||||
readme_section,
|
||||
)
|
||||
end
|
||||
@kwdef struct Citation <: BasicPlugin
|
||||
file::String = default_file("CITATION.bib")
|
||||
readme::Bool = false
|
||||
end
|
||||
|
||||
tags(::Citation) = "<<", ">>"
|
||||
|
||||
source(p::Citation) = p.file
|
||||
destination(::Citation) = "CITATION.bib"
|
||||
|
||||
view(::Citation, t::Template, pkg::AbstractString) = Dict(
|
||||
"AUTHORS" => t.authors,
|
||||
"MONTH" => month(today()),
|
||||
"PKG" => pkg,
|
||||
"URL" => "https://$(t.host)/$(t.user)/$pkg.jl",
|
||||
"YEAR" => year(today()),
|
||||
)
|
||||
|
||||
function interactive(::Type{Citation})
|
||||
print("Citation: Add a section to README.md mentioning CITATION.bib? [no]: ")
|
||||
readme = uppercase(readline()) in ["Y", "YES", "TRUE"]
|
||||
readme = prompt_bool("Citation: Add a section to the README", false)
|
||||
return Citation(; readme_section=readme)
|
||||
end
|
||||
|
||||
|
||||
function gen_plugin(p::Citation, t::Template, pkg_name::AbstractString)
|
||||
pkg_dir = joinpath(t.dir, pkg_name)
|
||||
text = """
|
||||
@misc{$pkg_name.jl,
|
||||
\tauthor = {$(t.authors)},
|
||||
\ttitle = {{$(pkg_name).jl}},
|
||||
\turl = {https://$(t.host)/$(t.user)/$(pkg_name).jl},
|
||||
\tversion = {v0.1.0},
|
||||
\tyear = {$(year(today()))},
|
||||
\tmonth = {$(month(today()))}
|
||||
}
|
||||
"""
|
||||
gen_file(joinpath(pkg_dir, "CITATION.bib"), text)
|
||||
return ["CITATION.bib"]
|
||||
end
|
||||
|
@ -1,44 +0,0 @@
|
||||
"""
|
||||
Codecov(; config_file::Union{AbstractString, Nothing}=nothing) -> Codecov
|
||||
|
||||
Add `Codecov` to a template's plugins to optionally add a `.codecov.yml` configuration file
|
||||
to generated repositories, and an appropriate badge to the README. Also updates the
|
||||
`.gitignore` accordingly.
|
||||
|
||||
# Keyword Arguments:
|
||||
* `config_file::Union{AbstractString, Nothing}=nothing`: Path to a custom `.codecov.yml`.
|
||||
If left unset, no file will be generated.
|
||||
"""
|
||||
struct Codecov <: GenericPlugin
|
||||
gitignore::Vector{String}
|
||||
src::Union{String, Nothing}
|
||||
dest::String
|
||||
badges::Vector{Badge}
|
||||
view::Dict{String, Any}
|
||||
|
||||
function Codecov(; config_file::Union{AbstractString, Nothing}=nothing)
|
||||
if config_file != nothing
|
||||
config_file = if isfile(config_file)
|
||||
abspath(config_file)
|
||||
else
|
||||
throw(ArgumentError("File $(abspath(config_file)) does not exist"))
|
||||
end
|
||||
end
|
||||
new(
|
||||
["*.jl.cov", "*.jl.*.cov", "*.jl.mem"],
|
||||
config_file,
|
||||
".codecov.yml",
|
||||
[
|
||||
Badge(
|
||||
"Codecov",
|
||||
"https://codecov.io/gh/{{USER}}/{{PKGNAME}}.jl/branch/master/graph/badge.svg",
|
||||
"https://codecov.io/gh/{{USER}}/{{PKGNAME}}.jl",
|
||||
),
|
||||
],
|
||||
Dict{String, Any}(),
|
||||
)
|
||||
end
|
||||
end
|
||||
Base.@deprecate_binding CodeCov Codecov
|
||||
|
||||
interactive(::Type{Codecov}) = interactive(Codecov; file=nothing)
|
31
src/plugins/coverage.jl
Normal file
31
src/plugins/coverage.jl
Normal file
@ -0,0 +1,31 @@
|
||||
abstract type Coverage <: Plugin end
|
||||
|
||||
const COVERAGE_GITIGNORE = ["*.jl.cov", "*.jl.*.cov", "*.jl.mem"]
|
||||
|
||||
gitignore(::Coverage) = COVERAGE_GITIGNORE
|
||||
|
||||
@kwdef struct Codecov <: Coverage
|
||||
file::Union{String, Nothing} = nothing
|
||||
end
|
||||
|
||||
source(p::Codecov) = p.file
|
||||
destination(::Codecov) = ".codecov.yml"
|
||||
|
||||
badges(::Codecov) = Badge(
|
||||
"Coverage",
|
||||
"https://codecov.io/gh/{{USER}}/{{PKG}}.jl/branch/master/graph/badge.svg",
|
||||
"https://codecov.io/gh/{{USER}}/{{PKG}}.jl",
|
||||
)
|
||||
|
||||
@kwdef struct Coveralls <: Coverage
|
||||
file::Union{String, Nothing} = nothing
|
||||
end
|
||||
|
||||
source(p::Coveralls) = p.file
|
||||
destination(::Coveralls) = ".coveralls.yml"
|
||||
|
||||
badges(::Coveralls) = Badge(
|
||||
"Coverage",
|
||||
"https://coveralls.io/repos/github/{{USER}}/{{PKG}}.jl/badge.svg?branch=master",
|
||||
"https://coveralls.io/github/{{USER}}/{{PKG}}.jl?branch=master",
|
||||
)
|
@ -1,43 +0,0 @@
|
||||
"""
|
||||
Coveralls(; config_file::Union{AbstractString, Nothing}=nothing) -> Coveralls
|
||||
|
||||
Add `Coveralls` to a template's plugins to optionally add a `.coveralls.yml` configuration
|
||||
file to generated repositories, and an appropriate badge to the README. Also updates the
|
||||
`.gitignore` accordingly.
|
||||
|
||||
# Keyword Arguments:
|
||||
* `config_file::Union{AbstractString, Nothing}=nothing`: Path to a custom `.coveralls.yml`.
|
||||
If left unset, no file will be generated.
|
||||
"""
|
||||
struct Coveralls <: GenericPlugin
|
||||
gitignore::Vector{String}
|
||||
src::Union{String, Nothing}
|
||||
dest::String
|
||||
badges::Vector{Badge}
|
||||
view::Dict{String, Any}
|
||||
|
||||
function Coveralls(; config_file::Union{AbstractString, Nothing}=nothing)
|
||||
if config_file != nothing
|
||||
config_file = if isfile(config_file)
|
||||
abspath(config_file)
|
||||
else
|
||||
throw(ArgumentError("File $(abspath(config_file)) does not exist"))
|
||||
end
|
||||
end
|
||||
new(
|
||||
["*.jl.cov", "*.jl.*.cov", "*.jl.mem"],
|
||||
config_file,
|
||||
".coveralls.yml",
|
||||
[
|
||||
Badge(
|
||||
"Coveralls",
|
||||
"https://coveralls.io/repos/github/{{USER}}/{{PKGNAME}}.jl/badge.svg?branch=master",
|
||||
"https://coveralls.io/github/{{USER}}/{{PKGNAME}}.jl?branch=master",
|
||||
),
|
||||
],
|
||||
Dict{String, Any}(),
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
interactive(::Type{Coveralls}) = interactive(Coveralls; file=nothing)
|
@ -1,31 +1,85 @@
|
||||
const DOCUMENTER_UUID = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
|
||||
const STANDARD_KWS = [:modules, :format, :pages, :repo, :sitename, :authors, :assets]
|
||||
|
||||
"""
|
||||
Add a `Documenter` subtype to a template's plugins to add support for documentation
|
||||
generation via [Documenter.jl](https://github.com/JuliaDocs/Documenter.jl).
|
||||
Documenter{T<:Union{TravisCI, GitLabCI, Nothing}}(;
|
||||
assets::Vector{<:AbstractString}=String[],
|
||||
makedocs_kwargs::Dict{Symbol}=Dict(),
|
||||
canonical_url::Union{Function, Nothing}=nothing,
|
||||
) -> Documenter{T}
|
||||
|
||||
By default, the plugin generates a minimal index.md and a make.jl file. The make.jl
|
||||
file contains the Documenter.makedocs command with predefined values for `modules`,
|
||||
`format`, `pages`, `repo`, `sitename`, and `authors`.
|
||||
The `Documenter` plugin adds support for documentation generation via [Documenter.jl](https://github.com/JuliaDocs/Documenter.jl).
|
||||
Documentation deployment depends on `T`, where `T` is some supported CI plugin, or `Nothing` to only support local documentation builds.
|
||||
|
||||
The subtype is expected to include the following fields:
|
||||
* `assets::Vector{AbstractString}`, a list of filenames to be included as the `assets`
|
||||
kwarg to `makedocs`
|
||||
* `gitignore::Vector{AbstractString}`, a list of files to be added to the `.gitignore`
|
||||
## Keyword Arguments
|
||||
todo
|
||||
- `assets::Vector{<:AbstractString}=String[]`:
|
||||
- `makedocs_kwargs::Dict{Symbol}=Dict{Symbol, Any}()`:
|
||||
- `canonical_url::Union{Function, Nothing}=nothing`:`
|
||||
|
||||
It may optionally include the field `additional_kwargs::Union{AbstractDict, NamedTuple}`
|
||||
to allow additional kwargs to be added to `makedocs`.
|
||||
!!! note
|
||||
If deploying documentation with Travis CI, don't forget to complete the required configuration.
|
||||
See [here](https://juliadocs.github.io/Documenter.jl/stable/man/hosting/#SSH-Deploy-Keys-1).
|
||||
"""
|
||||
abstract type Documenter <: CustomPlugin end
|
||||
struct Documenter{T<:Union{TravisCI, GitLabCI, Nothing}} <: Plugin
|
||||
assets::Vector{String}
|
||||
makedocs_kwargs::Dict{Symbol}
|
||||
canonical_url::Union{Function, Nothing}
|
||||
|
||||
function gen_plugin(p::Documenter, t::Template, pkg_name::AbstractString)
|
||||
path = joinpath(t.dir, pkg_name)
|
||||
docs_dir = joinpath(path, "docs")
|
||||
mkpath(docs_dir)
|
||||
# Can't use @kwdef due to some weird precompilation issues.
|
||||
function Documenter{T}(
|
||||
assets::Vector{<:AbstractString}=String[],
|
||||
makedocs_kwargs::Dict{Symbol}=Dict{Symbol, Any}(),
|
||||
canonical_url::Union{Function, Nothing}=T === TravisCI ? github_pages_url : nothing,
|
||||
) where T <: Union{TravisCI, GitLabCI, Nothing}
|
||||
return new(assets, makedocs_kwargs, canonical_url)
|
||||
end
|
||||
end
|
||||
|
||||
Documenter(; kwargs...) = Documenter{Nothing}(; kwargs...)
|
||||
|
||||
gitignore(::Documenter) = ["/docs/build/", "/docs/site/"]
|
||||
|
||||
badges(::Documenter) = Badge[]
|
||||
badges(::Documenter{TravisCI}) = [
|
||||
Badge(
|
||||
"Stable",
|
||||
"https://img.shields.io/badge/docs-stable-blue.svg",
|
||||
"https://{{USER}}.github.io/{{PKG}}.jl/stable",
|
||||
),
|
||||
Badge(
|
||||
"Dev",
|
||||
"https://img.shields.io/badge/docs-dev-blue.svg",
|
||||
"https://{{USER}}.github.io/{{PKG}}.jl/dev",
|
||||
),
|
||||
]
|
||||
badges(::Documenter{GitLabCI}) = Badge(
|
||||
"Dev",
|
||||
"https://img.shields.io/badge/docs-dev-blue.svg",
|
||||
"https://{{USER}}.gitlab.io/{{PKG}}.jl/dev",
|
||||
)
|
||||
|
||||
view(p::Documenter, t::Template, pkg::AbstractString) = Dict(
|
||||
"ASSETS" => p.assets,
|
||||
"AUTHORS" => t.authors,
|
||||
"CANONICAL" => p.canonical_url === nothing ? nothing : p.canonical_url(t, pkg),
|
||||
"HAS_ASSETS" => !isempty(p.assets),
|
||||
"MAKEDOCS_KWARGS" => map((k, v) -> k => repr(v), collect(p.makedocs_kwargs)),
|
||||
"PKG" => pkg,
|
||||
"REPO" => "https://$(t.host)/$(t.user)/$pkg.jl",
|
||||
)
|
||||
|
||||
function view(p::Documenter{TravisCI}, t::Template, pkg::AbstractString)
|
||||
base = invoke(view, Tuple{Documenter, Template, AbstractString}, p, t, pkg)
|
||||
return merge(base, Dict("HAS_DEPLOY" => true))
|
||||
end
|
||||
|
||||
function gen_plugin(p::Documenter, t::Template, pkg_dir::AbstractString)
|
||||
# TODO: gen make.jl
|
||||
# TODO: gen index.md
|
||||
|
||||
# Create the documentation project.
|
||||
proj = Base.current_project()
|
||||
docs_dir = joinpath(pkg_dir, "docs")
|
||||
proj = current_project()
|
||||
try
|
||||
Pkg.activate(docs_dir)
|
||||
Pkg.add(PackageSpec(; name="Documenter", uuid=DOCUMENTER_UUID))
|
||||
@ -33,95 +87,38 @@ function gen_plugin(p::Documenter, t::Template, pkg_name::AbstractString)
|
||||
proj === nothing ? Pkg.activate() : Pkg.activate(proj)
|
||||
end
|
||||
|
||||
tab = repeat(" ", 4)
|
||||
assets_string = if !isempty(p.assets)
|
||||
mkpath(joinpath(docs_dir, "src", "assets"))
|
||||
for file in p.assets
|
||||
cp(file, joinpath(docs_dir, "src", "assets", basename(file)))
|
||||
end
|
||||
|
||||
# We want something that looks like the following:
|
||||
# [
|
||||
# assets/file1,
|
||||
# assets/file2,
|
||||
# ]
|
||||
s = "[\n"
|
||||
for asset in p.assets
|
||||
s *= """$(tab^2)"assets/$(basename(asset))",\n"""
|
||||
end
|
||||
s *= "$tab]"
|
||||
|
||||
s
|
||||
else
|
||||
"String[]"
|
||||
end
|
||||
|
||||
kwargs_string = if :additional_kwargs in fieldnames(typeof(p)) &&
|
||||
fieldtype(typeof(p), :additional_kwargs) <: Union{AbstractDict, NamedTuple}
|
||||
# We want something that looks like the following:
|
||||
# key1="val1",
|
||||
# key2="val2",
|
||||
#
|
||||
kws = [keys(p.additional_kwargs)...]
|
||||
valid_keys = filter(k -> !in(Symbol(k), STANDARD_KWS), kws)
|
||||
if length(p.additional_kwargs) > length(valid_keys)
|
||||
invalid_keys = filter(k -> Symbol(k) in STANDARD_KWS, kws)
|
||||
@warn string(
|
||||
"Ignoring predefined Documenter kwargs ",
|
||||
join(map(repr, invalid_keys), ", "),
|
||||
" from additional kwargs"
|
||||
)
|
||||
end
|
||||
join(map(k -> string(tab, k, "=", repr(p.additional_kwargs[k]), ",\n"), valid_keys))
|
||||
else
|
||||
""
|
||||
end
|
||||
|
||||
make = """
|
||||
using Documenter, $pkg_name
|
||||
|
||||
makedocs(;
|
||||
modules=[$pkg_name],
|
||||
format=Documenter.HTML(),
|
||||
pages=[
|
||||
"Home" => "index.md",
|
||||
],
|
||||
repo="https://$(t.host)/$(t.user)/$pkg_name.jl/blob/{commit}{path}#L{line}",
|
||||
sitename="$pkg_name.jl",
|
||||
authors="$(t.authors)",
|
||||
assets=$assets_string,
|
||||
$kwargs_string)
|
||||
"""
|
||||
docs = """
|
||||
# $pkg_name.jl
|
||||
|
||||
```@index
|
||||
```
|
||||
|
||||
```@autodocs
|
||||
Modules = [$pkg_name]
|
||||
```
|
||||
"""
|
||||
|
||||
gen_file(joinpath(docs_dir, "make.jl"), make)
|
||||
gen_file(joinpath(docs_dir, "src", "index.md"), docs)
|
||||
# Copy any assets.
|
||||
assets_dir = joinpath(docs_dir, "src", "assets")
|
||||
isempty(p.assets) || mkpath(assets_dir)
|
||||
foreach(a -> cp(a, joinpath(assets_dir, basename(asset))), p.assets)
|
||||
end
|
||||
|
||||
function Base.show(io::IO, p::Documenter)
|
||||
spc = " "
|
||||
println(io, nameof(typeof(p)), ":")
|
||||
function interactive(::Type{Documenter{T}}) where T
|
||||
name = "Documenter{$T}"
|
||||
|
||||
n = length(p.assets)
|
||||
s = n == 1 ? "" : "s"
|
||||
print(io, spc, "→ $n asset file$s")
|
||||
if n == 0
|
||||
println(io)
|
||||
else
|
||||
println(io, ": ", join(map(a -> replace(a, homedir() => "~"), p.assets), ", "))
|
||||
print("$name: Enter any Documenter asset files (separated by spaces) [none]: ")
|
||||
assets = split(readline())
|
||||
|
||||
print("$name: Enter any extra makedocs key-value pairs (joined by '=') [none]\n> ")
|
||||
kwargs = Dict{Symbol, Any}()
|
||||
line = map(split(readline())) do kv
|
||||
k, v = split(kv, "="; limit=2)
|
||||
kwargs[Symbol(k)] = eval(Meta.parse(v))
|
||||
end
|
||||
|
||||
n = length(p.gitignore)
|
||||
s = n == 1 ? "" : "s"
|
||||
print(io, "$spc→ $n gitignore entrie$s")
|
||||
n > 0 && print(io, ": ", join(map(repr, p.gitignore), ", "))
|
||||
return Documenter{T}(; assets=assets, kwargs=kwargs)
|
||||
end
|
||||
|
||||
function interactive(::Type{Documenter})
|
||||
types = Dict(
|
||||
"None (local documentation only)" => Nothing,
|
||||
"TravisCI (GitHub Pages)" => TravisCI,
|
||||
"GitLabCI (GitLab Pages)" => GitLabCI,
|
||||
)
|
||||
options = collect(keys(types))
|
||||
menu = RadioMenu(options)
|
||||
T = types[options[request("Documenter: Select integration:", menu)]]
|
||||
return interactive(Documenter{T})
|
||||
end
|
||||
|
||||
github_pages_url(t::Template, pkg::AbstractString) = "https://$(t.user).github.io/$pkg.jl"
|
||||
|
115
src/plugins/essentials.jl
Normal file
115
src/plugins/essentials.jl
Normal file
@ -0,0 +1,115 @@
|
||||
const LICENSE_DIR = normpath(joinpath(@__DIR__, "..", "..", "licenses"))
|
||||
const LICENSES = Dict(
|
||||
"MIT" => "MIT \"Expat\" License",
|
||||
"BSD2" => "Simplified \"2-clause\" BSD License",
|
||||
"BSD3" => "Modified \"3-clause\" BSD License",
|
||||
"ISC" => "Internet Systems Consortium License",
|
||||
"ASL" => "Apache License, Version 2.0",
|
||||
"MPL" => "Mozilla Public License, Version 2.0",
|
||||
"GPL-2.0+" => "GNU Public License, Version 2.0+",
|
||||
"GPL-3.0+" => "GNU Public License, Version 3.0+",
|
||||
"LGPL-2.1+" => "Lesser GNU Public License, Version 2.1+",
|
||||
"LGPL-3.0+" => "Lesser GNU Public License, Version 3.0+",
|
||||
"EUPL-1.2+" => "European Union Public Licence, Version 1.2+",
|
||||
)
|
||||
|
||||
@kwdef 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(::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)
|
||||
text *= "\n" * join(badges(t.plugins[T], t.user, pkg), "\n")
|
||||
end
|
||||
|
||||
return Dict(
|
||||
"HAS_CITATION" => hasplugin(t, Citation),
|
||||
"HAS_INLINE_BADGES" => p.inline_badges,
|
||||
)
|
||||
end
|
||||
|
||||
struct License <: Plugin
|
||||
path::String
|
||||
destination::String
|
||||
|
||||
function License(name::AbstractString="MIT", destination::AbstractString="LICENSE")
|
||||
return new(license_path(name), destination)
|
||||
end
|
||||
end
|
||||
|
||||
function license_path(license::AbstractString)
|
||||
path = joinpath(LICENSE_DIR, license)
|
||||
isfile(path) || throw(ArgumentError("License '$license' is not available"))
|
||||
return path
|
||||
end
|
||||
|
||||
read_license(license::AbstractString) = string(readchomp(license_path(license)))
|
||||
|
||||
function render_plugin(p::License, t::Template)
|
||||
text = "Copyright (c) $(year(today())) $(t.authors)\n"
|
||||
license = read(p.path, String)
|
||||
startswith(license, "\n") || (text *= "\n")
|
||||
return text * license
|
||||
end
|
||||
|
||||
function gen_plugin(p::License, t::Template, pkg_dir::AbstractString)
|
||||
gen_file(joinpath(pkg_dir, p.destination), render_plugin(p, t))
|
||||
end
|
||||
|
||||
struct Gitignore <: Plugin end
|
||||
|
||||
function render_plugin(p::Gitignore, t::Template)
|
||||
entries = mapreduce(gitignore, append!, values(t.plugins); init=[".DS_Store", "/dev/"])
|
||||
# Only ignore manifests at the repo root.
|
||||
t.manifest || "Manifest.toml" in entries || push!(entries, "/Manifest.toml")
|
||||
unique!(sort!(entries))
|
||||
return join(entries, "\n")
|
||||
end
|
||||
|
||||
function gen_plugin(p::Gitignore, t::Template, pkg_dir::AbstractString)
|
||||
gen_file(joinpath(pkg_dir, ".gitignore"), render_plugin(p, t))
|
||||
end
|
||||
|
||||
@kwdef struct Tests <: BasicPlugin
|
||||
file::String = default_file("runtests.jl")
|
||||
end
|
||||
|
||||
source(p::Tests) = p.file
|
||||
destination(::Tests) = joinpath("test", "runtests.jl")
|
||||
view(::Tests, ::Template, pkg::AbstractString) = Dict("PKG" => pkg)
|
||||
|
||||
function gen_plugin(p::Tests, t::Template, pkg_dir::AbstractString)
|
||||
# Do the normal BasicPlugin behaviour to create the test script.
|
||||
invoke(gen_plugin, Tuple{BasicPlugin, Template, AbstractString}, p, t, pkg_dir)
|
||||
|
||||
# Add the Test dependency as a test-only dependency.
|
||||
# To avoid visual noise from adding/removing the dependency, insert it manually.
|
||||
proj = current_project()
|
||||
try
|
||||
Pkg.activate(pkg_dir)
|
||||
lines = readlines(joinpath(pkg_dir, "Project.toml"))
|
||||
dep = "Test = $(repr(TEST_UUID))"
|
||||
push!(lines, "[extras]", dep, "", "[targets]", "test = [\"Test\"]")
|
||||
gen_file(joinpath(pkg_dir, "Project.toml"), join(lines, "\n"))
|
||||
touch(joinpath(pkg_dir, "Manifest.toml")) # File must exist to be modified by Pkg.
|
||||
Pkg.update() # Clean up both Manifest.toml and Project.toml.
|
||||
finally
|
||||
proj === nothing ? Pkg.activate() : Pkg.activate(proj)
|
||||
end
|
||||
end
|
@ -1,69 +0,0 @@
|
||||
"""
|
||||
GitHubPages(; assets::Vector{<:AbstractString}=String[]) -> GitHubPages
|
||||
|
||||
Add `GitHubPages` to a template's plugins to add [`Documenter`](@ref) support via GitHub
|
||||
Pages, including automatic uploading of documentation from [`TravisCI`](@ref). Also
|
||||
adds appropriate badges to the README, and updates the `.gitignore` accordingly.
|
||||
|
||||
# Keyword Arguments
|
||||
* `assets::Vector{<:AbstractString}=String[]`: Array of paths to Documenter asset files.
|
||||
|
||||
!!! note
|
||||
If deploying documentation with Travis CI, don't forget to complete the required
|
||||
configuration (see
|
||||
[here](https://juliadocs.github.io/Documenter.jl/stable/man/hosting/#SSH-Deploy-Keys-1)).
|
||||
"""
|
||||
struct GitHubPages <: Documenter
|
||||
gitignore::Vector{String}
|
||||
assets::Vector{String}
|
||||
|
||||
function GitHubPages(; assets::Vector{<:AbstractString}=String[])
|
||||
for file in assets
|
||||
if !isfile(file)
|
||||
throw(ArgumentError("Asset file $(abspath(file)) does not exist"))
|
||||
end
|
||||
end
|
||||
# Windows Git recognizes these paths as well.
|
||||
new(["/docs/build/", "/docs/site/"], abspath.(assets))
|
||||
end
|
||||
end
|
||||
|
||||
function badges(::GitHubPages, user::AbstractString, pkg_name::AbstractString)
|
||||
return [
|
||||
format(Badge(
|
||||
"Stable",
|
||||
"https://img.shields.io/badge/docs-stable-blue.svg",
|
||||
"https://$user.github.io/$pkg_name.jl/stable"
|
||||
)),
|
||||
format(Badge(
|
||||
"Dev",
|
||||
"https://img.shields.io/badge/docs-dev-blue.svg",
|
||||
"https://$user.github.io/$pkg_name.jl/dev"
|
||||
)),
|
||||
]
|
||||
end
|
||||
|
||||
function gen_plugin(p::GitHubPages, t::Template, pkg_name::AbstractString)
|
||||
invoke(gen_plugin, Tuple{Documenter, Template, AbstractString}, p, t, pkg_name)
|
||||
|
||||
if haskey(t.plugins, TravisCI)
|
||||
docs_src = joinpath(t.dir, pkg_name, "docs", "src")
|
||||
open(joinpath(dirname(docs_src), "make.jl"), "a") do file
|
||||
write(
|
||||
file,
|
||||
"""
|
||||
|
||||
deploydocs(;
|
||||
repo="$(t.host)/$(t.user)/$pkg_name.jl",
|
||||
)
|
||||
"""
|
||||
)
|
||||
end
|
||||
end
|
||||
return ["docs/"]
|
||||
end
|
||||
|
||||
function interactive(::Type{GitHubPages})
|
||||
print("GitHubPages: Enter any Documenter asset files (separated by spaces) []: ")
|
||||
return GitHubPages(; assets=string.(split(readline())))
|
||||
end
|
@ -1,83 +0,0 @@
|
||||
"""
|
||||
GitLabCI(; config_file::Union{AbstractString, Nothing}="", coverage::Bool=true) -> GitLabCI
|
||||
|
||||
Add `GitLabCI` to a template's plugins to add a `.gitlab-ci.yml` configuration file to
|
||||
generated repositories, and appropriate badge(s) to the README.
|
||||
|
||||
# Keyword Arguments:
|
||||
* `config_file::Union{AbstractString, Nothing}=""`: Path to a custom `.gitlab-ci.yml`.
|
||||
If `nothing` is supplied, no file will be generated.
|
||||
* `coverage::Bool=true`: Whether or not GitLab CI's built-in code coverage analysis should
|
||||
be enabled.
|
||||
"""
|
||||
struct GitLabCI <: GenericPlugin
|
||||
gitignore::Vector{String}
|
||||
src::Union{String, Nothing}
|
||||
dest::String
|
||||
badges::Vector{Badge}
|
||||
view::Dict{String, Any}
|
||||
|
||||
function GitLabCI(; config_file::Union{AbstractString, Nothing}="", coverage::Bool=true)
|
||||
if config_file != nothing
|
||||
config_file = if isempty(config_file)
|
||||
config_file = joinpath(DEFAULTS_DIR, "gitlab-ci.yml")
|
||||
elseif isfile(config_file)
|
||||
abspath(config_file)
|
||||
else
|
||||
throw(ArgumentError("File $(abspath(config_file)) does not exist"))
|
||||
end
|
||||
end
|
||||
badges = [
|
||||
Badge(
|
||||
"Build Status",
|
||||
"https://gitlab.com/{{USER}}/{{PKGNAME}}.jl/badges/master/build.svg",
|
||||
"https://gitlab.com/{{USER}}/{{PKGNAME}}.jl/pipelines",
|
||||
),
|
||||
]
|
||||
if coverage
|
||||
push!(
|
||||
badges,
|
||||
Badge(
|
||||
"Coverage",
|
||||
"https://gitlab.com/{{USER}}/{{PKGNAME}}.jl/badges/master/coverage.svg",
|
||||
"https://gitlab.com/{{USER}}/{{PKGNAME}}.jl/commits/master",
|
||||
),
|
||||
)
|
||||
end
|
||||
|
||||
new(
|
||||
coverage ? ["*.jl.cov", "*.jl.*.cov", "*.jl.mem"] : [],
|
||||
config_file,
|
||||
".gitlab-ci.yml",
|
||||
badges,
|
||||
Dict("GITLABCOVERAGE" => coverage),
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
function interactive(::Type{GitLabCI})
|
||||
name = "GitLabCI"
|
||||
kwargs = Dict{Symbol, Any}()
|
||||
default_config_file = joinpath(DEFAULTS_DIR, "gitlab-ci.yml")
|
||||
|
||||
print("$name: Enter the config template filename (\"None\" for no file) ")
|
||||
print("[", replace(default_config_file, homedir() => "~"), "]: ")
|
||||
config_file = readline()
|
||||
kwargs[:config_file] = if uppercase(config_file) == "NONE"
|
||||
nothing
|
||||
elseif isempty(config_file)
|
||||
default_config_file
|
||||
else
|
||||
config_file
|
||||
end
|
||||
|
||||
print("$name: Enable test coverage analysis? [yes]: ")
|
||||
coverage = readline()
|
||||
kwargs[:coverage] = if isempty(coverage)
|
||||
true
|
||||
else
|
||||
!in(uppercase(coverage), ["N", "NO", "FALSE", "NONE"])
|
||||
end
|
||||
|
||||
return GitLabCI(; kwargs...)
|
||||
end
|
@ -1,47 +0,0 @@
|
||||
"""
|
||||
GitLabPages(; assets::Vector{<:AbstractString}=String[]) -> GitLabPages
|
||||
|
||||
Add `GitLabPages` to a template's plugins to add [`Documenter`](@ref) support via GitLab
|
||||
Pages, including automatic uploading of documentation from [`GitLabCI`](@ref). Also
|
||||
adds appropriate badges to the README, and updates the `.gitignore` accordingly.
|
||||
|
||||
# Keyword Arguments
|
||||
* `assets::Vector{<:AbstractString}=String[]`: Array of paths to Documenter asset files.
|
||||
"""
|
||||
struct GitLabPages <: Documenter
|
||||
gitignore::Vector{String}
|
||||
assets::Vector{String}
|
||||
|
||||
function GitLabPages(; assets::Vector{<:AbstractString}=String[])
|
||||
for file in assets
|
||||
if !isfile(file)
|
||||
throw(ArgumentError("Asset file $(abspath(file)) does not exist"))
|
||||
end
|
||||
end
|
||||
# Windows Git recognizes these paths as well.
|
||||
new(["/docs/build/", "/docs/site/"], abspath.(assets))
|
||||
end
|
||||
end
|
||||
|
||||
function badges(::GitLabPages, user::AbstractString, pkg_name::AbstractString)
|
||||
# We are only including a badge for `dev` documentation since versioned documentation
|
||||
# is not supported in GitLab pages yet. See:
|
||||
# https://github.com/invenia/PkgTemplates.jl/pull/54
|
||||
return [
|
||||
format(Badge(
|
||||
"Dev",
|
||||
"https://img.shields.io/badge/docs-dev-blue.svg",
|
||||
"https://$user.gitlab.io/$pkg_name.jl/dev"
|
||||
)),
|
||||
]
|
||||
end
|
||||
|
||||
function gen_plugin(p::GitLabPages, t::Template, pkg_name::AbstractString)
|
||||
invoke(gen_plugin, Tuple{Documenter, Template, AbstractString}, p, t, pkg_name)
|
||||
return ["docs/"]
|
||||
end
|
||||
|
||||
function interactive(::Type{GitLabPages})
|
||||
print("GitLabPages: Enter any Documenter asset files (separated by spaces) []: ")
|
||||
return GitLabPages(; assets=string.(split(readline())))
|
||||
end
|
@ -1,44 +0,0 @@
|
||||
"""
|
||||
TravisCI(; config_file::Union{AbstractString, Nothing}="") -> TravisCI
|
||||
|
||||
Add `TravisCI` to a template's plugins to add a `.travis.yml` configuration file to
|
||||
generated repositories, and an appropriate badge to the README.
|
||||
|
||||
# Keyword Arguments:
|
||||
* `config_file::Union{AbstractString, Nothing}=""`: Path to a custom `.travis.yml`.
|
||||
If `nothing` is supplied, no file will be generated.
|
||||
"""
|
||||
struct TravisCI <: GenericPlugin
|
||||
gitignore::Vector{String}
|
||||
src::Union{String, Nothing}
|
||||
dest::String
|
||||
badges::Vector{Badge}
|
||||
view::Dict{String, Any}
|
||||
|
||||
function TravisCI(; config_file::Union{AbstractString, Nothing}="")
|
||||
if config_file != nothing
|
||||
config_file = if isempty(config_file)
|
||||
config_file = joinpath(DEFAULTS_DIR, "travis.yml")
|
||||
elseif isfile(config_file)
|
||||
abspath(config_file)
|
||||
else
|
||||
throw(ArgumentError("File $(abspath(config_file)) does not exist"))
|
||||
end
|
||||
end
|
||||
new(
|
||||
[],
|
||||
config_file,
|
||||
".travis.yml",
|
||||
[
|
||||
Badge(
|
||||
"Build Status",
|
||||
"https://travis-ci.com/{{USER}}/{{PKGNAME}}.jl.svg?branch=master",
|
||||
"https://travis-ci.com/{{USER}}/{{PKGNAME}}.jl",
|
||||
),
|
||||
],
|
||||
Dict{String, Any}(),
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
interactive(::Type{TravisCI}) = interactive(TravisCI; file="travis.yml")
|
305
src/template.jl
305
src/template.jl
@ -1,242 +1,107 @@
|
||||
default_version() = VersionNumber(VERSION.major)
|
||||
|
||||
"""
|
||||
Template(; kwargs...) -> Template
|
||||
Template(interactive::Bool=false; kwargs...) -> Template
|
||||
|
||||
Records common information used to generate a package. If you don't wish to manually
|
||||
create a template, you can use [`interactive_template`](@ref) instead.
|
||||
Records common information used to generate a package.
|
||||
|
||||
# Keyword Arguments
|
||||
* `user::AbstractString=""`: GitHub (or other code hosting service) username. If left
|
||||
unset, it will take the the global git config's value (`github.user`). If that is not
|
||||
set, an `ArgumentError` is thrown. **This is case-sensitive for some plugins, so take
|
||||
care to enter it correctly.**
|
||||
* `host::AbstractString="github.com"`: URL to the code hosting service where your package
|
||||
will reside. Note that while hosts other than GitHub won't cause errors, they are not
|
||||
officially supported and they will cause certain plugins will produce incorrect output.
|
||||
* `license::AbstractString="MIT"`: Name of the package license. If an empty string is
|
||||
given, no license is created. [`available_licenses`](@ref) can be used to list all
|
||||
available licenses, and [`show_license`](@ref) can be used to print out a particular
|
||||
license's text.
|
||||
* `authors::Union{AbstractString, Vector{<:AbstractString}}=""`: Names that appear on the
|
||||
license. Supply a string for one author or an array for multiple. Similarly to `user`,
|
||||
it will take the value of of the global git config's value if it is left unset.
|
||||
* `dir::AbstractString=$(replace(Pkg.devdir(), homedir() => "~"))`: Directory in which the
|
||||
package will go. Relative paths are converted to absolute ones at template creation time.
|
||||
* `julia_version::VersionNumber=$(default_version())`: Minimum allowed Julia version.
|
||||
* `ssh::Bool=false`: Whether or not to use SSH for the git remote. If `false` HTTPS will be used.
|
||||
* `dev::Bool=true`: Whether or not to `Pkg.develop` generated packages.
|
||||
* `manifest::Bool=false`: Whether or not to commit the `Manifest.toml`.
|
||||
* `plugins::Vector{<:Plugin}=Plugin[]`: A list of `Plugin`s that the package will include.
|
||||
## Keyword Arguments
|
||||
- `user::AbstractString=""`: GitHub (or other code hosting service) username.
|
||||
If left unset, it will take the the global Git config's value (`github.user`).
|
||||
If that is not set, an `ArgumentError` is thrown.
|
||||
This is case-sensitive for some plugins, so take care to enter it correctly!
|
||||
- `host::AbstractString="github.com"`: URL to the code hosting service where your package will reside.
|
||||
Note that while hosts other than GitHub won't cause errors, they are not officially supported and they will cause certain plugins will produce incorrect output.
|
||||
- `authors::Union{AbstractString, Vector{<:AbstractString}}=""`: Names that appear on the license.
|
||||
Supply a string for one author or an array for multiple.
|
||||
Similarly to `user`, it will take the value of of the global Git config's value if it is left unset.
|
||||
- `dir::AbstractString=$(contractuser(Pkg.devdir()))`: Directory in which the package will go.
|
||||
Relative paths are converted to absolute ones at template creation time.
|
||||
- `julia_version::VersionNumber=$DEFAULT_VERSION`: Minimum allowed Julia version.
|
||||
- `ssh::Bool=false`: Whether or not to use SSH for the git remote. If `false` HTTPS will be used.
|
||||
- `manifest::Bool=false`: Whether or not to commit the `Manifest.toml`.
|
||||
- `git::Bool=true`: Whether or not to create a Git repository for generated packages.
|
||||
- `develop::Bool=true`: Whether or not to `develop` generated packages in the active environment.
|
||||
- `plugins::Vector{<:Plugin}=Plugin[]`: A list of plugins that the package will include.
|
||||
- `disable_default_plugins::Vector{DataType}=DataType[]`: Default plugins to disable.
|
||||
The default plugins are [`Readme`](@ref), [`License`](@ref), [`Tests`](@ref), and [`Gitignore`](@ref).
|
||||
To override a default plugin instead of disabling it altogether, supply it via `plugins`.
|
||||
- `interactive::Bool=false`: When set, creates the template interactively from user input,
|
||||
using the previous keywords as a starting point.
|
||||
- `fast::Bool=false`: Only applicable when `interactive` is set.
|
||||
Skips prompts for any unsupplied keywords except `user` and `plugins`.
|
||||
"""
|
||||
struct Template
|
||||
user::String
|
||||
host::String
|
||||
license::String
|
||||
authors::String
|
||||
dir::String
|
||||
julia_version::VersionNumber
|
||||
ssh::Bool
|
||||
dev::Bool
|
||||
manifest::Bool
|
||||
git::Bool
|
||||
develop::Bool
|
||||
plugins::Dict{DataType, <:Plugin}
|
||||
end
|
||||
|
||||
function Template(;
|
||||
user::AbstractString="",
|
||||
host::AbstractString="https://github.com",
|
||||
license::AbstractString="MIT",
|
||||
authors::Union{AbstractString, Vector{<:AbstractString}}="",
|
||||
dir::AbstractString=Pkg.devdir(),
|
||||
julia_version::VersionNumber=default_version(),
|
||||
ssh::Bool=false,
|
||||
dev::Bool=true,
|
||||
manifest::Bool=false,
|
||||
plugins::Vector{<:Plugin}=Plugin[],
|
||||
git::Bool=true,
|
||||
Template(; interactive::Bool=false, kwargs...) = make_template(Val(interactive); kwargs...)
|
||||
|
||||
function make_template(::Val{false}; kwargs...)
|
||||
user = getkw(kwargs, :user)
|
||||
if isempty(user)
|
||||
throw(ArgumentError("No username found, set one with user=username"))
|
||||
end
|
||||
|
||||
host = getkw(kwargs, :host)
|
||||
host = URI(occursin("://", host) ? host : "https://$host").host
|
||||
|
||||
authors = getkw(kwargs, :authors)
|
||||
authors isa Vector && (authors = join(authors, ", "))
|
||||
|
||||
dir = abspath(expanduser(getkw(kwargs, :dir)))
|
||||
|
||||
disabled = getkw(kwargs, :disabled_defaults)
|
||||
defaults = [Readme, License, Tests, Gitignore]
|
||||
plugins = map(T -> T(), filter(T -> !in(T, disabled), defaults))
|
||||
append!(plugins, getkw(kwargs, :plugins))
|
||||
# This comprehensions resolves duplicate plugin types by overwriting,
|
||||
# which means that default plugins get replaced by user values.
|
||||
plugin_dict = Dict(typeof(p) => p for p in plugins)
|
||||
|
||||
return Template(
|
||||
user,
|
||||
host,
|
||||
authors,
|
||||
dir,
|
||||
getkw(kwargs, :julia_version),
|
||||
getkw(kwargs, :ssh),
|
||||
getkw(kwargs, :manifest),
|
||||
getkw(kwargs, :git),
|
||||
getkw(kwargs, :develop),
|
||||
plugin_dict,
|
||||
)
|
||||
# Check for required Git options for package generation
|
||||
# (you can't commit to a repository without them).
|
||||
git && isempty(LibGit2.getconfig("user.name", "")) && missingopt("user.name")
|
||||
git && isempty(LibGit2.getconfig("user.email", "")) && missingopt("user.email")
|
||||
|
||||
# If no username was set, look for one in the global git config.
|
||||
# Note: This is one of a few GitHub specifics (maybe we could use the host value).
|
||||
if isempty(user)
|
||||
user = LibGit2.getconfig("github.user", "")
|
||||
end
|
||||
if isempty(user)
|
||||
throw(ArgumentError("No GitHub username found, set one with user=username"))
|
||||
end
|
||||
|
||||
host = URI(startswith(host, "https://") ? host : "https://$host").host
|
||||
|
||||
if !isempty(license) && !isfile(joinpath(LICENSE_DIR, license))
|
||||
throw(ArgumentError("License '$license' is not available"))
|
||||
end
|
||||
|
||||
# If no author was set, look for one in the global git config.
|
||||
if isempty(authors)
|
||||
authors = LibGit2.getconfig("user.name", "")
|
||||
email = LibGit2.getconfig("user.email", "")
|
||||
isempty(email) || (authors *= " <$email>")
|
||||
elseif authors isa Vector
|
||||
authors = join(authors, ", ")
|
||||
end
|
||||
|
||||
dir = abspath(expanduser(dir))
|
||||
|
||||
plugin_dict = Dict{DataType, Plugin}(typeof(p) => p for p in plugins)
|
||||
if (length(plugins) != length(plugin_dict))
|
||||
@warn "Plugin list contained duplicates, only the last of each type was kept"
|
||||
end
|
||||
|
||||
new(user, host, license, authors, dir, julia_version, ssh, dev, manifest, plugin_dict)
|
||||
end
|
||||
end
|
||||
|
||||
function Base.show(io::IO, t::Template)
|
||||
maybe(s::String) = isempty(s) ? "None" : s
|
||||
spc = " "
|
||||
hasplugin(t::Template, ::Type{T}) where T <: Plugin = any(U -> U <: T, keys(t.plugins))
|
||||
|
||||
println(io, "Template:")
|
||||
println(io, spc, "→ User: ", maybe(t.user))
|
||||
println(io, spc, "→ Host: ", maybe(t.host))
|
||||
getkw(kwargs, k) = get(() -> defaultkw(k), kwargs, k)
|
||||
|
||||
print(io, spc, "→ License: ")
|
||||
if isempty(t.license)
|
||||
println(io, "None")
|
||||
else
|
||||
println(io, t.license, " ($(t.authors) ", year(today()), ")")
|
||||
end
|
||||
|
||||
println(io, spc, "→ Package directory: ", replace(maybe(t.dir), homedir() => "~"))
|
||||
println(io, spc, "→ Minimum Julia version: v", version_floor(t.julia_version))
|
||||
println(io, spc, "→ SSH remote: ", t.ssh ? "Yes" : "No")
|
||||
println(io, spc, "→ Add packages to main environment: ", t.dev ? "Yes" : "No")
|
||||
println(io, spc, "→ Commit Manifest.toml: ", t.manifest ? "Yes" : "No")
|
||||
|
||||
print(io, spc, "→ Plugins:")
|
||||
if isempty(t.plugins)
|
||||
print(io, " None")
|
||||
else
|
||||
for plugin in sort(collect(values(t.plugins)); by=string)
|
||||
println(io)
|
||||
buf = IOBuffer()
|
||||
show(buf, plugin)
|
||||
print(io, spc^2, "• ")
|
||||
print(io, join(split(String(take!(buf)), "\n"), "\n$(spc^2)"))
|
||||
end
|
||||
end
|
||||
defaultkw(s::Symbol) = defaultkw(Val(s))
|
||||
defaultkw(::Val{:user}) = LibGit2.getconfig("github.user", "")
|
||||
defaultkw(::Val{:host}) = "https://github.com"
|
||||
defaultkw(::Val{:dir}) = Pkg.devdir()
|
||||
defaultkw(::Val{:julia_version}) = DEFAULT_VERSION
|
||||
defaultkw(::Val{:ssh}) = false
|
||||
defaultkw(::Val{:manifest}) = false
|
||||
defaultkw(::Val{:git}) = true
|
||||
defaultkw(::Val{:develop}) = true
|
||||
defaultkw(::Val{:plugins}) = Plugin[]
|
||||
defaultkw(::Val{:disabled_defaults}) = DataType[]
|
||||
function defaultkw(::Val{:authors})
|
||||
name = LibGit2.getconfig("user.name", "")
|
||||
email = LibGit2.getconfig("user.email", "")
|
||||
isempty(name) && return ""
|
||||
author = name * " "
|
||||
isempty(email) || (author *= "<$email>")
|
||||
return strip(author)
|
||||
end
|
||||
|
||||
"""
|
||||
interactive_template(; fast::Bool=false) -> Template
|
||||
|
||||
Interactively create a [`Template`](@ref). If `fast` is set, defaults will be assumed for
|
||||
all values except username and plugins.
|
||||
"""
|
||||
function interactive_template(; git::Bool=true, fast::Bool=false)
|
||||
@info "Default values are shown in [brackets]"
|
||||
# Getting the leaf types in a separate thread eliminates an awkward wait after
|
||||
# "Select plugins" is printed.
|
||||
plugin_types = @async leaves(Plugin)
|
||||
kwargs = Dict{Symbol, Any}()
|
||||
|
||||
default_user = LibGit2.getconfig("github.user", "")
|
||||
print("Username [", isempty(default_user) ? "REQUIRED" : default_user, "]: ")
|
||||
user = readline()
|
||||
kwargs[:user] = if !isempty(user)
|
||||
user
|
||||
elseif !isempty(default_user)
|
||||
default_user
|
||||
else
|
||||
throw(ArgumentError("Username is required"))
|
||||
end
|
||||
|
||||
kwargs[:host] = if fast || !git
|
||||
"https://github.com" # If Git isn't enabled, this value never gets used.
|
||||
else
|
||||
default_host = "github.com"
|
||||
print("Code hosting service [$default_host]: ")
|
||||
host = readline()
|
||||
isempty(host) ? default_host : host
|
||||
end
|
||||
|
||||
kwargs[:license] = if fast
|
||||
"MIT"
|
||||
else
|
||||
println("License:")
|
||||
io = IOBuffer()
|
||||
available_licenses(io)
|
||||
licenses = ["" => "", collect(LICENSES)...]
|
||||
menu = RadioMenu(String["None", split(String(take!(io)), "\n")...])
|
||||
# If the user breaks out of the menu with Ctrl-c, the result is -1, the absolute
|
||||
# value of which correponds to no license.
|
||||
first(licenses[abs(request(menu))])
|
||||
end
|
||||
|
||||
# We don't need to ask for authors if there is no license,
|
||||
# because the license is the only place that they matter.
|
||||
kwargs[:authors] = if fast || isempty(kwargs[:license])
|
||||
LibGit2.getconfig("user.name", "")
|
||||
else
|
||||
default_authors = LibGit2.getconfig("user.name", "")
|
||||
default_str = isempty(default_authors) ? "None" : default_authors
|
||||
print("Package author(s) [$default_str]: ")
|
||||
authors = readline()
|
||||
isempty(authors) ? default_authors : authors
|
||||
end
|
||||
|
||||
kwargs[:dir] = if fast
|
||||
Pkg.devdir()
|
||||
else
|
||||
default_dir = Pkg.devdir()
|
||||
print("Path to package directory [$default_dir]: ")
|
||||
dir = readline()
|
||||
isempty(dir) ? default_dir : dir
|
||||
end
|
||||
|
||||
kwargs[:julia_version] = if fast
|
||||
VERSION
|
||||
else
|
||||
default_julia_version = VERSION
|
||||
print("Minimum Julia version [", version_floor(default_julia_version), "]: ")
|
||||
julia_version = readline()
|
||||
isempty(julia_version) ? default_julia_version : VersionNumber(julia_version)
|
||||
end
|
||||
|
||||
kwargs[:ssh] = if fast || !git
|
||||
false
|
||||
else
|
||||
print("Set remote to SSH? [no]: ")
|
||||
uppercase(readline()) in ["Y", "YES", "T", "TRUE"]
|
||||
end
|
||||
|
||||
kwargs[:dev] = if fast
|
||||
true
|
||||
else
|
||||
print("Add packages to main environment? [yes]: ")
|
||||
uppercase(readline()) in ["", "Y", "YES", "T", "TRUE"]
|
||||
end
|
||||
|
||||
kwargs[:manifest] = if fast
|
||||
false
|
||||
else
|
||||
print("Commit Manifest.toml? [no]: ")
|
||||
uppercase(readline()) in ["Y", "YES", "T", "TRUE"]
|
||||
end
|
||||
|
||||
println("Plugins:")
|
||||
# Only include plugin types which have an `interactive` method.
|
||||
plugin_types = filter(t -> hasmethod(interactive, (Type{t},)), fetch(plugin_types))
|
||||
type_names = map(t -> split(string(t), ".")[end], plugin_types)
|
||||
menu = MultiSelectMenu(String.(type_names); pagesize=length(type_names))
|
||||
selected = collect(request(menu))
|
||||
kwargs[:plugins] = Vector{Plugin}(map(interactive, getindex(plugin_types, selected)))
|
||||
|
||||
return Template(; git=git, kwargs...)
|
||||
end
|
||||
|
||||
leaves(T::Type)::Vector{DataType} = isconcretetype(T) ? [T] : vcat(leaves.(subtypes(T))...)
|
||||
|
||||
missingopt(name) = @warn "Git config option '$name' missing, package generation will fail unless you supply a GitConfig"
|
||||
|
@ -1,3 +0,0 @@
|
||||
[user]
|
||||
name = Travis
|
||||
email = travis@c.i
|
@ -1,68 +0,0 @@
|
||||
@testset "Interactive mode" begin
|
||||
@testset "Template creation" begin
|
||||
write(stdin.buffer, "$me\n\n\r\n\n\n\n\nd")
|
||||
t = interactive_template()
|
||||
@test t.user == me
|
||||
@test t.host == "github.com"
|
||||
@test isempty(t.license)
|
||||
@test t.authors == LibGit2.getconfig("user.name", "")
|
||||
@test t.dir == default_dir
|
||||
@test t.julia_version == VERSION
|
||||
@test !t.ssh
|
||||
@test t.dev
|
||||
@test !t.manifest
|
||||
@test isempty(t.plugins)
|
||||
|
||||
if isempty(LibGit2.getconfig("github.user", ""))
|
||||
write(stdin.buffer, "\n")
|
||||
@test_throws ArgumentError t = interactive_template()
|
||||
end
|
||||
|
||||
down = '\x1b' * "[B" # Down array key.
|
||||
write(stdin.buffer, "$me\ngitlab.com\n$down\r$me\n$test_file\n0.5\nyes\nno\nyes\n$down\r$down\rd\n\n")
|
||||
t = interactive_template()
|
||||
@test t.user == me
|
||||
@test t.host == "gitlab.com"
|
||||
# Not sure if the order the licenses are displayed in is consistent.
|
||||
@test !isempty(t.license)
|
||||
@test t.authors == me
|
||||
@test t.dir == abspath(test_file)
|
||||
@test t.julia_version == v"0.5.0"
|
||||
@test t.ssh
|
||||
@test !t.dev
|
||||
@test t.manifest
|
||||
# Like above, not sure which plugins this will generate.
|
||||
@test length(t.plugins) == 2
|
||||
|
||||
write(stdin.buffer, "$me\nd")
|
||||
t = interactive_template(; fast=true)
|
||||
@test t.user == me
|
||||
@test t.host == "github.com"
|
||||
@test t.license == "MIT"
|
||||
@test t.authors == LibGit2.getconfig("user.name", "")
|
||||
@test t.dir == default_dir
|
||||
@test t.julia_version == VERSION
|
||||
@test !t.ssh
|
||||
@test !t.manifest
|
||||
@test isempty(t.plugins)
|
||||
println()
|
||||
|
||||
# Host and SSH aren't prompted for when git is disabled.
|
||||
write(stdin.buffer, "$me\n\n\r\n\n\n\nd")
|
||||
t = interactive_template(; git=false)
|
||||
@test t.host == "github.com"
|
||||
@test !t.ssh
|
||||
println()
|
||||
end
|
||||
|
||||
@testset "Package generation" begin
|
||||
write(stdin.buffer, "$me\n\n\r\n\n\n\n\n\n\n\nd")
|
||||
generate_interactive(test_pkg; gitconfig=gitconfig)
|
||||
@test isdir(joinpath(default_dir, test_pkg))
|
||||
rm(joinpath(default_dir, test_pkg); force=true, recursive=true)
|
||||
end
|
||||
|
||||
@testset "Plugins" begin
|
||||
include("plugins.jl")
|
||||
end
|
||||
end
|
@ -1,90 +0,0 @@
|
||||
# These tests are to be skipped in OSX builds, see ./interactive.jl for more info.
|
||||
|
||||
@testset "TravisCI" begin
|
||||
write(stdin.buffer, "\n")
|
||||
p = interactive(TravisCI)
|
||||
@test p.src == joinpath(DEFAULTS_DIR, "travis.yml")
|
||||
write(stdin.buffer, "$test_file\n")
|
||||
p = interactive(TravisCI)
|
||||
@test p.src == test_file
|
||||
write(stdin.buffer, "none\n")
|
||||
p = interactive(TravisCI)
|
||||
@test p.src === nothing
|
||||
write(stdin.buffer, "$fake_path\n")
|
||||
@test_throws ArgumentError interactive(TravisCI)
|
||||
println()
|
||||
end
|
||||
|
||||
@testset "AppVeyor" begin
|
||||
write(stdin.buffer, "\n")
|
||||
p = interactive(AppVeyor)
|
||||
@test p.src == joinpath(DEFAULTS_DIR, "appveyor.yml")
|
||||
write(stdin.buffer, "$test_file\n")
|
||||
p = interactive(AppVeyor)
|
||||
@test p.src == test_file
|
||||
write(stdin.buffer, "none\n")
|
||||
p = interactive(AppVeyor)
|
||||
@test p.src === nothing
|
||||
write(stdin.buffer, "$fake_path\n")
|
||||
@test_throws ArgumentError interactive(AppVeyor)
|
||||
println()
|
||||
end
|
||||
|
||||
@testset "GitLabCI" begin
|
||||
write(stdin.buffer, "\n\n")
|
||||
p = interactive(GitLabCI)
|
||||
@test p.src == joinpath(DEFAULTS_DIR, "gitlab-ci.yml")
|
||||
@test p.view == Dict("GITLABCOVERAGE" => true)
|
||||
write(stdin.buffer, "$test_file\nno\n")
|
||||
p = interactive(GitLabCI)
|
||||
@test p.src == test_file
|
||||
@test p.view == Dict("GITLABCOVERAGE" => false)
|
||||
write(stdin.buffer, "none\n\n")
|
||||
p = interactive(GitLabCI)
|
||||
@test p.src === nothing
|
||||
write(stdin.buffer, "$fake_path\n\n")
|
||||
@test_throws ArgumentError interactive(GitLabCI)
|
||||
println()
|
||||
end
|
||||
|
||||
@testset "Codecov" begin
|
||||
write(stdin.buffer, "\n")
|
||||
p = interactive(Codecov)
|
||||
@test p.src === nothing
|
||||
write(stdin.buffer, "$test_file\n")
|
||||
p = interactive(Codecov)
|
||||
@test p.src == test_file
|
||||
write(stdin.buffer, "none\n")
|
||||
p = interactive(Codecov)
|
||||
@test p.src === nothing
|
||||
write(stdin.buffer, "$fake_path\n")
|
||||
@test_throws ArgumentError interactive(Codecov)
|
||||
println()
|
||||
end
|
||||
|
||||
@testset "Coveralls" begin
|
||||
write(stdin.buffer, "\n")
|
||||
p = interactive(Coveralls)
|
||||
@test p.src === nothing
|
||||
write(stdin.buffer, "$test_file\n")
|
||||
p = interactive(Coveralls)
|
||||
@test p.src == test_file
|
||||
write(stdin.buffer, "none\n")
|
||||
p = interactive(Coveralls)
|
||||
@test p.src === nothing
|
||||
write(stdin.buffer, "$fake_path\n")
|
||||
@test_throws ArgumentError interactive(Coveralls)
|
||||
println()
|
||||
end
|
||||
|
||||
@testset "GitHubPages" begin
|
||||
write(stdin.buffer, "\n")
|
||||
p = interactive(GitHubPages)
|
||||
@test isempty(p.assets)
|
||||
write(stdin.buffer, "$test_file\n")
|
||||
p = interactive(GitHubPages)
|
||||
@test p.assets == [test_file]
|
||||
write(stdin.buffer, "$fake_path\n")
|
||||
@test_throws ArgumentError interactive(GitHubPages)
|
||||
println()
|
||||
end
|
@ -1,57 +0,0 @@
|
||||
t = Template(; user=me)
|
||||
pkg_dir = joinpath(t.dir, test_pkg)
|
||||
|
||||
@testset "AppVeyor" begin
|
||||
@testset "Plugin creation" begin
|
||||
p = AppVeyor()
|
||||
@test isempty(p.gitignore)
|
||||
@test p.src == joinpath(PkgTemplates.DEFAULTS_DIR, "appveyor.yml")
|
||||
@test p.dest == ".appveyor.yml"
|
||||
@test p.badges == [
|
||||
Badge(
|
||||
"Build Status",
|
||||
"https://ci.appveyor.com/api/projects/status/github/{{USER}}/{{PKGNAME}}.jl?svg=true",
|
||||
"https://ci.appveyor.com/project/{{USER}}/{{PKGNAME}}-jl",
|
||||
),
|
||||
]
|
||||
@test isempty(p.view)
|
||||
p = AppVeyor(; config_file=nothing)
|
||||
@test p.src === nothing
|
||||
p = AppVeyor(; config_file=test_file)
|
||||
@test p.src == test_file
|
||||
@test_throws ArgumentError AppVeyor(; config_file=fake_path)
|
||||
end
|
||||
|
||||
@testset "Badge generation" begin
|
||||
p = AppVeyor()
|
||||
@test badges(p, me, test_pkg) == ["[](https://ci.appveyor.com/project/$me/$test_pkg-jl)"]
|
||||
end
|
||||
|
||||
@testset "File generation" begin
|
||||
# Without a coverage plugin in the template, there should be no post-test step.
|
||||
p = AppVeyor()
|
||||
@test gen_plugin(p, t, test_pkg) == [".appveyor.yml"]
|
||||
@test isfile(joinpath(pkg_dir, ".appveyor.yml"))
|
||||
appveyor = read(joinpath(pkg_dir, ".appveyor.yml"), String)
|
||||
@test !occursin("on_success", appveyor)
|
||||
@test !occursin("%JL_CODECOV_SCRIPT%", appveyor)
|
||||
rm(joinpath(pkg_dir, ".appveyor.yml"))
|
||||
|
||||
# Generating the plugin with Codecov in the template should create a post-test step.
|
||||
t.plugins[Codecov] = Codecov()
|
||||
gen_plugin(p, t, test_pkg)
|
||||
delete!(t.plugins, Codecov)
|
||||
appveyor = read(joinpath(pkg_dir, ".appveyor.yml"), String)
|
||||
@test occursin("on_success", appveyor)
|
||||
@test occursin("%JL_CODECOV_SCRIPT%", appveyor)
|
||||
rm(joinpath(pkg_dir, ".appveyor.yml"))
|
||||
|
||||
# TODO: Add Coveralls tests when AppVeyor.jl supports it.
|
||||
|
||||
p = AppVeyor(; config_file=nothing)
|
||||
@test isempty(gen_plugin(p, t, test_pkg))
|
||||
@test !isfile(joinpath(pkg_dir, ".appveyor.yml"))
|
||||
end
|
||||
end
|
||||
|
||||
rm(pkg_dir; recursive=true)
|
@ -1,54 +0,0 @@
|
||||
t = Template(; user=me)
|
||||
pkg_dir = joinpath(t.dir, test_pkg)
|
||||
|
||||
@testset "CirrusCI" begin
|
||||
@testset "Plugin creation" begin
|
||||
p = CirrusCI()
|
||||
@test isempty(p.gitignore)
|
||||
@test p.src == joinpath(DEFAULTS_DIR, "cirrus.yml")
|
||||
@test p.dest == ".cirrus.yml"
|
||||
@test p.badges == [
|
||||
Badge(
|
||||
"Build Status",
|
||||
"https://api.cirrus-ci.com/github/{{USER}}/{{PKGNAME}}.jl.svg",
|
||||
"https://cirrus-ci.com/github/{{USER}}/{{PKGNAME}}.jl",
|
||||
),
|
||||
]
|
||||
@test isempty(p.view)
|
||||
p = CirrusCI(; config_file=nothing)
|
||||
@test p.src === nothing
|
||||
p = CirrusCI(; config_file=test_file)
|
||||
@test p.src == test_file
|
||||
@test_throws ArgumentError CirrusCI(; config_file=fake_path)
|
||||
end
|
||||
|
||||
@testset "Badge generation" begin
|
||||
p = CirrusCI()
|
||||
@test badges(p, me, test_pkg) == ["[](https://cirrus-ci.com/github/$me/$test_pkg.jl)"]
|
||||
end
|
||||
|
||||
@testset "File generation" begin
|
||||
# Without a coverage plugin in the template, there should be no coverage step.
|
||||
p = CirrusCI()
|
||||
@test gen_plugin(p, t, test_pkg) == [".cirrus.yml"]
|
||||
@test isfile(joinpath(pkg_dir, ".cirrus.yml"))
|
||||
cirrus = read(joinpath(pkg_dir, ".cirrus.yml"), String)
|
||||
@test !occursin("coverage_script", cirrus)
|
||||
rm(joinpath(pkg_dir, ".cirrus.yml"))
|
||||
|
||||
# Generating the plugin with Codecov in the template should create a post-test step.
|
||||
t.plugins[Codecov] = Codecov()
|
||||
gen_plugin(p, t, test_pkg)
|
||||
delete!(t.plugins, Codecov)
|
||||
cirrus = read(joinpath(pkg_dir, ".cirrus.yml"), String)
|
||||
@test occursin("coverage_script", cirrus)
|
||||
@test occursin("cirrusjl coverage", cirrus)
|
||||
rm(joinpath(pkg_dir, ".cirrus.yml"))
|
||||
|
||||
p = CirrusCI(; config_file=nothing)
|
||||
@test isempty(gen_plugin(p, t, test_pkg))
|
||||
@test !isfile(joinpath(pkg_dir, ".cirrus.yml"))
|
||||
end
|
||||
end
|
||||
|
||||
rm(pkg_dir; recursive=true)
|
@ -1,48 +0,0 @@
|
||||
t = Template(; user=me)
|
||||
pkg_dir = joinpath(t.dir, test_pkg)
|
||||
|
||||
@testset "CITATION" begin
|
||||
@testset "Plugin creation" begin
|
||||
p = Citation()
|
||||
@test isempty(p.gitignore)
|
||||
@test p.dest == "CITATION.bib"
|
||||
@test isempty(p.badges)
|
||||
@test isempty(p.view)
|
||||
@test !p.readme_section
|
||||
p = Citation(; readme_section=true)
|
||||
@test p.readme_section
|
||||
end
|
||||
|
||||
@testset "File generation" begin
|
||||
p = Citation()
|
||||
@test gen_plugin(p, t, test_pkg) == ["CITATION.bib"]
|
||||
@test isfile(joinpath(pkg_dir, "CITATION.bib"))
|
||||
citation = read(joinpath(pkg_dir, "CITATION.bib"), String)
|
||||
|
||||
@test occursin("@misc", citation)
|
||||
@test occursin("$(t.authors)", citation)
|
||||
@test occursin("v0.1.0", citation)
|
||||
end
|
||||
|
||||
@testset "Readme untouched" begin
|
||||
p = Citation(; readme_section=false)
|
||||
t.plugins[Citation] = p
|
||||
isdir(pkg_dir) && rm(pkg_dir; recursive=true)
|
||||
generate(test_pkg, t, git=false)
|
||||
readme = read(joinpath(pkg_dir, "README.md"), String)
|
||||
@test !occursin("## Citing", readme)
|
||||
@test !occursin("CITATION.bib", readme)
|
||||
end
|
||||
|
||||
@testset "Readme modification" begin
|
||||
p = Citation(; readme_section=true)
|
||||
t.plugins[Citation] = p
|
||||
isdir(pkg_dir) && rm(pkg_dir; recursive=true)
|
||||
generate(test_pkg, t, git=false)
|
||||
readme = read(joinpath(pkg_dir, "README.md"), String)
|
||||
@test occursin("## Citing", readme)
|
||||
@test occursin("CITATION.bib", readme)
|
||||
end
|
||||
end
|
||||
|
||||
rm(pkg_dir; recursive=true)
|
@ -1,41 +0,0 @@
|
||||
t = Template(; user=me)
|
||||
pkg_dir = joinpath(t.dir, test_pkg)
|
||||
|
||||
@testset "Codecov" begin
|
||||
@testset "Plugin creation" begin
|
||||
p = Codecov()
|
||||
@test p.gitignore == ["*.jl.cov", "*.jl.*.cov", "*.jl.mem"]
|
||||
@test p.src === nothing
|
||||
@test p.dest == ".codecov.yml"
|
||||
@test p.badges == [
|
||||
Badge(
|
||||
"Codecov",
|
||||
"https://codecov.io/gh/{{USER}}/{{PKGNAME}}.jl/branch/master/graph/badge.svg",
|
||||
"https://codecov.io/gh/{{USER}}/{{PKGNAME}}.jl",
|
||||
)
|
||||
]
|
||||
@test isempty(p.view)
|
||||
p = Codecov(; config_file=nothing)
|
||||
@test p.src === nothing
|
||||
p = Codecov(; config_file=test_file)
|
||||
@test p.src == test_file
|
||||
@test_throws ArgumentError Codecov(; config_file=fake_path)
|
||||
end
|
||||
|
||||
@testset "Badge generation" begin
|
||||
p = Codecov()
|
||||
@test badges(p, me, test_pkg) == ["[](https://codecov.io/gh/$me/$test_pkg.jl)"]
|
||||
end
|
||||
|
||||
@testset "File generation" begin
|
||||
p = Codecov()
|
||||
@test isempty(gen_plugin(p, t, test_pkg))
|
||||
@test !isfile(joinpath(pkg_dir, ".codecov.yml"))
|
||||
|
||||
p = Codecov(; config_file=test_file)
|
||||
@test gen_plugin(p, t, test_pkg) == [".codecov.yml"]
|
||||
@test isfile(joinpath(pkg_dir, ".codecov.yml"))
|
||||
end
|
||||
end
|
||||
|
||||
rm(pkg_dir; recursive=true)
|
@ -1,40 +0,0 @@
|
||||
t = Template(; user=me)
|
||||
pkg_dir = joinpath(t.dir, test_pkg)
|
||||
|
||||
@testset "Coveralls" begin
|
||||
@testset "Plugin creation" begin
|
||||
p = Coveralls()
|
||||
@test p.gitignore == ["*.jl.cov", "*.jl.*.cov", "*.jl.mem"]
|
||||
@test p.src === nothing
|
||||
@test p.dest == ".coveralls.yml"
|
||||
@test p.badges == [
|
||||
Badge(
|
||||
"Coveralls",
|
||||
"https://coveralls.io/repos/github/{{USER}}/{{PKGNAME}}.jl/badge.svg?branch=master",
|
||||
"https://coveralls.io/github/{{USER}}/{{PKGNAME}}.jl?branch=master",
|
||||
)
|
||||
]
|
||||
@test isempty(p.view)
|
||||
p = Coveralls(; config_file=nothing)
|
||||
@test p.src === nothing
|
||||
p = Coveralls(; config_file=test_file)
|
||||
@test p.src == test_file
|
||||
@test_throws ArgumentError Coveralls(; config_file=fake_path)
|
||||
end
|
||||
|
||||
@testset "Badge generation" begin
|
||||
p = Coveralls()
|
||||
@test badges(p, me, test_pkg) == ["[](https://coveralls.io/github/$me/$test_pkg.jl?branch=master)"]
|
||||
end
|
||||
|
||||
@testset "File generation" begin
|
||||
p = Coveralls()
|
||||
@test isempty(gen_plugin(p, t, test_pkg))
|
||||
@test !isfile(joinpath(pkg_dir, ".coveralls.yml"))
|
||||
p = Coveralls(; config_file=test_file)
|
||||
@test gen_plugin(p, t, test_pkg) == [".coveralls.yml"]
|
||||
@test isfile(joinpath(pkg_dir, ".coveralls.yml"))
|
||||
end
|
||||
end
|
||||
|
||||
rm(pkg_dir; recursive=true)
|
@ -1,68 +0,0 @@
|
||||
t = Template(; user=me)
|
||||
pkg_dir = joinpath(t.dir, test_pkg)
|
||||
|
||||
@testset "GitHubPages" begin
|
||||
@testset "Plugin creation" begin
|
||||
p = GitHubPages()
|
||||
@test p.gitignore == ["/docs/build/", "/docs/site/"]
|
||||
@test isempty(p.assets)
|
||||
p = GitHubPages(; assets=[test_file])
|
||||
@test p.assets == [test_file]
|
||||
@test_throws ArgumentError GitHubPages(; assets=[fake_path])
|
||||
end
|
||||
|
||||
@testset "Badge generation" begin
|
||||
p = GitHubPages()
|
||||
@test badges(p, me, test_pkg) == [
|
||||
"[](https://$me.github.io/$test_pkg.jl/stable)"
|
||||
"[](https://$me.github.io/$test_pkg.jl/dev)"
|
||||
]
|
||||
end
|
||||
|
||||
@testset "File generation" begin
|
||||
p = GitHubPages()
|
||||
@test gen_plugin(p, t, test_pkg) == ["docs/"]
|
||||
@test isdir(joinpath(pkg_dir, "docs"))
|
||||
@test isfile(joinpath(pkg_dir, "docs", "make.jl"))
|
||||
make = readchomp(joinpath(pkg_dir, "docs", "make.jl"))
|
||||
@test occursin("assets=String[]", make)
|
||||
@test !occursin("deploydocs", make)
|
||||
@test isdir(joinpath(pkg_dir, "docs", "src"))
|
||||
@test isfile(joinpath(pkg_dir, "docs", "src", "index.md"))
|
||||
index = readchomp(joinpath(pkg_dir, "docs", "src", "index.md"))
|
||||
@test occursin("autodocs", index)
|
||||
rm(joinpath(pkg_dir, "docs"); recursive=true)
|
||||
p = GitHubPages(; assets=[test_file])
|
||||
@test gen_plugin(p, t, test_pkg) == ["docs/"]
|
||||
make = readchomp(joinpath(pkg_dir, "docs", "make.jl"))
|
||||
# Check the formatting of the assets list.
|
||||
@test occursin(
|
||||
strip("""
|
||||
assets=[
|
||||
"assets/$(basename(test_file))",
|
||||
]
|
||||
"""),
|
||||
make,
|
||||
)
|
||||
@test isfile(joinpath(pkg_dir, "docs", "src", "assets", basename(test_file)))
|
||||
rm(joinpath(pkg_dir, "docs"); recursive=true)
|
||||
t.plugins[TravisCI] = TravisCI()
|
||||
@test gen_plugin(p, t, test_pkg) == ["docs/"]
|
||||
make = readchomp(joinpath(pkg_dir, "docs", "make.jl"))
|
||||
@test occursin("deploydocs", make)
|
||||
rm(joinpath(pkg_dir, "docs"); recursive=true)
|
||||
end
|
||||
|
||||
@testset "Package generation with GitHubPages plugin" begin
|
||||
temp_dir = mktempdir()
|
||||
t = Template(; user=me, dir=temp_dir, plugins=[GitHubPages()])
|
||||
generate(test_pkg, t; gitconfig=gitconfig)
|
||||
|
||||
# Check that the gh-pages branch exists.
|
||||
repo = LibGit2.GitRepo(joinpath(t.dir, test_pkg))
|
||||
branches = map(b -> LibGit2.shortname(first(b)), LibGit2.GitBranchIter(repo))
|
||||
@test in("gh-pages", branches)
|
||||
end
|
||||
end
|
||||
|
||||
rm(pkg_dir; recursive=true)
|
@ -1,69 +0,0 @@
|
||||
t = Template(; user=me)
|
||||
pkg_dir = joinpath(t.dir, test_pkg)
|
||||
|
||||
@testset "GitLabCI" begin
|
||||
@testset "Plugin creation" begin
|
||||
p = GitLabCI()
|
||||
@test p.gitignore == ["*.jl.cov", "*.jl.*.cov", "*.jl.mem"]
|
||||
@test p.src == joinpath(PkgTemplates.DEFAULTS_DIR, "gitlab-ci.yml")
|
||||
@test p.dest == ".gitlab-ci.yml"
|
||||
@test p.badges == [
|
||||
Badge(
|
||||
"Build Status",
|
||||
"https://gitlab.com/{{USER}}/{{PKGNAME}}.jl/badges/master/build.svg",
|
||||
"https://gitlab.com/{{USER}}/{{PKGNAME}}.jl/pipelines",
|
||||
),
|
||||
Badge(
|
||||
"Coverage",
|
||||
"https://gitlab.com/{{USER}}/{{PKGNAME}}.jl/badges/master/coverage.svg",
|
||||
"https://gitlab.com/{{USER}}/{{PKGNAME}}.jl/commits/master",
|
||||
),
|
||||
]
|
||||
@test p.view == Dict("GITLABCOVERAGE" => true)
|
||||
p = GitLabCI(; config_file=nothing)
|
||||
@test p.src === nothing
|
||||
p = GitLabCI(; config_file=test_file)
|
||||
@test p.src == test_file
|
||||
@test_throws ArgumentError GitLabCI(; config_file=fake_path)
|
||||
p = GitLabCI(; coverage=false)
|
||||
@test p.badges == [
|
||||
Badge(
|
||||
"Build Status",
|
||||
"https://gitlab.com/{{USER}}/{{PKGNAME}}.jl/badges/master/build.svg",
|
||||
"https://gitlab.com/{{USER}}/{{PKGNAME}}.jl/pipelines",
|
||||
),
|
||||
]
|
||||
@test p.view == Dict("GITLABCOVERAGE" => false)
|
||||
end
|
||||
|
||||
@testset "Badge generation" begin
|
||||
p = GitLabCI()
|
||||
@test badges(p, me, test_pkg) == [
|
||||
"[](https://gitlab.com/$me/$test_pkg.jl/pipelines)",
|
||||
"[](https://gitlab.com/$me/$test_pkg.jl/commits/master)",
|
||||
]
|
||||
end
|
||||
|
||||
@testset "File generation" begin
|
||||
p = GitLabCI()
|
||||
@test gen_plugin(p, t, test_pkg) == [".gitlab-ci.yml"]
|
||||
@test isfile(joinpath(pkg_dir, ".gitlab-ci.yml"))
|
||||
gitlab = read(joinpath(pkg_dir, ".gitlab-ci.yml"), String)
|
||||
# The default plugin should enable the coverage step.
|
||||
@test occursin("using Coverage", gitlab)
|
||||
rm(joinpath(pkg_dir, ".gitlab-ci.yml"))
|
||||
|
||||
p = GitLabCI(; coverage=false)
|
||||
gen_plugin(p, t, test_pkg)
|
||||
gitlab = read(joinpath(pkg_dir, ".gitlab-ci.yml"), String)
|
||||
# If coverage is false, there should be no coverage step.
|
||||
@test !occursin("using Coverage", gitlab)
|
||||
rm(joinpath(pkg_dir, ".gitlab-ci.yml"))
|
||||
p = GitLabCI(; config_file=nothing)
|
||||
|
||||
@test isempty(gen_plugin(p, t, test_pkg))
|
||||
@test !isfile(joinpath(pkg_dir, ".gitlab-ci.yml"))
|
||||
end
|
||||
end
|
||||
|
||||
rm(pkg_dir; recursive=true)
|
@ -1,60 +0,0 @@
|
||||
t = Template(; user=me)
|
||||
pkg_dir = joinpath(t.dir, test_pkg)
|
||||
|
||||
@testset "GitLabPages" begin
|
||||
@testset "Plugin creation" begin
|
||||
p = GitLabPages()
|
||||
@test p.gitignore == ["/docs/build/", "/docs/site/"]
|
||||
@test isempty(p.assets)
|
||||
p = GitLabPages(; assets=[test_file])
|
||||
@test p.assets == [test_file]
|
||||
@test_throws ArgumentError GitLabPages(; assets=[fake_path])
|
||||
end
|
||||
|
||||
@testset "Badge generation" begin
|
||||
p = GitLabPages()
|
||||
@test badges(p, me, test_pkg) == [
|
||||
"[](https://$me.gitlab.io/$test_pkg.jl/dev)"
|
||||
]
|
||||
end
|
||||
|
||||
@testset "File generation" begin
|
||||
p = GitLabPages()
|
||||
@test gen_plugin(p, t, test_pkg) == ["docs/"]
|
||||
@test isdir(joinpath(pkg_dir, "docs"))
|
||||
@test isfile(joinpath(pkg_dir, "docs", "make.jl"))
|
||||
make = readchomp(joinpath(pkg_dir, "docs", "make.jl"))
|
||||
@test occursin("assets=String[]", make)
|
||||
@test !occursin("deploydocs", make)
|
||||
@test isdir(joinpath(pkg_dir, "docs", "src"))
|
||||
@test isfile(joinpath(pkg_dir, "docs", "src", "index.md"))
|
||||
index = readchomp(joinpath(pkg_dir, "docs", "src", "index.md"))
|
||||
@test occursin("autodocs", index)
|
||||
rm(joinpath(pkg_dir, "docs"); recursive=true)
|
||||
p = GitLabPages(; assets=[test_file])
|
||||
@test gen_plugin(p, t, test_pkg) == ["docs/"]
|
||||
make = readchomp(joinpath(pkg_dir, "docs", "make.jl"))
|
||||
# Check the formatting of the assets list.
|
||||
@test occursin(
|
||||
strip("""
|
||||
assets=[
|
||||
"assets/$(basename(test_file))",
|
||||
]
|
||||
"""),
|
||||
make,
|
||||
)
|
||||
@test isfile(joinpath(pkg_dir, "docs", "src", "assets", basename(test_file)))
|
||||
rm(joinpath(pkg_dir, "docs"); recursive=true)
|
||||
end
|
||||
|
||||
@testset "Package generation with GitLabPages plugin" begin
|
||||
temp_dir = mktempdir()
|
||||
t = Template(; user=me, dir=temp_dir, plugins=[GitLabCI(), GitLabPages()])
|
||||
generate(test_pkg, t; gitconfig=gitconfig)
|
||||
|
||||
gitlab = read(joinpath(t.dir, test_pkg, ".gitlab-ci.yml"), String)
|
||||
@test occursin("pages:", gitlab)
|
||||
end
|
||||
end
|
||||
|
||||
rm(pkg_dir; recursive=true)
|
@ -1,82 +0,0 @@
|
||||
t = Template(; user=me)
|
||||
pkg_dir = joinpath(t.dir, test_pkg)
|
||||
|
||||
@testset "TravisCI" begin
|
||||
@testset "Plugin creation" begin
|
||||
p = TravisCI()
|
||||
@test isempty(p.gitignore)
|
||||
@test p.src == joinpath(PkgTemplates.DEFAULTS_DIR, "travis.yml")
|
||||
@test p.dest == ".travis.yml"
|
||||
@test p.badges == [
|
||||
Badge(
|
||||
"Build Status",
|
||||
"https://travis-ci.com/{{USER}}/{{PKGNAME}}.jl.svg?branch=master",
|
||||
"https://travis-ci.com/{{USER}}/{{PKGNAME}}.jl",
|
||||
),
|
||||
]
|
||||
@test isempty(p.view)
|
||||
p = TravisCI(; config_file=nothing)
|
||||
@test p.src === nothing
|
||||
p = TravisCI(; config_file=test_file)
|
||||
@test p.src == test_file
|
||||
@test_throws ArgumentError TravisCI(; config_file=fake_path)
|
||||
end
|
||||
|
||||
@testset "Badge generation" begin
|
||||
p = TravisCI()
|
||||
@test badges(p, me, test_pkg) == ["[](https://travis-ci.com/$me/$test_pkg.jl)"]
|
||||
end
|
||||
|
||||
@testset "File generation" begin
|
||||
# Without a coverage plugin in the template, there should be no post-test step.
|
||||
p = TravisCI()
|
||||
@test gen_plugin(p, t, test_pkg) == [".travis.yml"]
|
||||
@test isfile(joinpath(pkg_dir, ".travis.yml"))
|
||||
travis = read(joinpath(pkg_dir, ".travis.yml"), String)
|
||||
|
||||
@test !occursin("after_success", travis)
|
||||
@test !occursin("Codecov.submit", travis)
|
||||
@test !occursin("Coveralls.submit", travis)
|
||||
@test !occursin("stage: Documentation", travis)
|
||||
rm(joinpath(pkg_dir, ".travis.yml"))
|
||||
|
||||
# Generating the plugin with Codecov in the template should create a post-test step.
|
||||
t.plugins[Codecov] = Codecov()
|
||||
gen_plugin(p, t, test_pkg)
|
||||
delete!(t.plugins, Codecov)
|
||||
travis = read(joinpath(pkg_dir, ".travis.yml"), String)
|
||||
@test occursin("after_success", travis)
|
||||
@test occursin("Codecov.submit", travis)
|
||||
@test !occursin("Coveralls.submit", travis)
|
||||
@test !occursin("stage: Documentation", travis)
|
||||
rm(joinpath(pkg_dir, ".travis.yml"))
|
||||
|
||||
# Coveralls should do the same.
|
||||
t.plugins[Coveralls] = Coveralls()
|
||||
gen_plugin(p, t, test_pkg)
|
||||
delete!(t.plugins, Coveralls)
|
||||
travis = read(joinpath(pkg_dir, ".travis.yml"), String)
|
||||
@test occursin("after_success", travis)
|
||||
@test occursin("Coveralls.submit", travis)
|
||||
@test !occursin("Codecov.submit", travis)
|
||||
@test !occursin("stage: Documentation", travis)
|
||||
rm(joinpath(pkg_dir, ".travis.yml"))
|
||||
|
||||
# With a Documenter plugin, there should be a docs deployment step.
|
||||
t.plugins[GitHubPages] = GitHubPages()
|
||||
gen_plugin(p, t, test_pkg)
|
||||
delete!(t.plugins, GitHubPages)
|
||||
travis = read(joinpath(pkg_dir, ".travis.yml"), String)
|
||||
@test occursin("after_success", travis)
|
||||
@test occursin("stage: Documentation", travis)
|
||||
@test !occursin("Codecov.submit", travis)
|
||||
@test !occursin("Coveralls.submit", travis)
|
||||
rm(joinpath(pkg_dir, ".travis.yml"))
|
||||
|
||||
p = TravisCI(; config_file=nothing)
|
||||
@test isempty(gen_plugin(p, t, test_pkg))
|
||||
@test !isfile(joinpath(pkg_dir, ".travis.yml"))
|
||||
end
|
||||
end
|
||||
|
||||
rm(pkg_dir; recursive=true)
|
@ -1,20 +0,0 @@
|
||||
using PkgTemplates
|
||||
using Test
|
||||
using Dates
|
||||
using LibGit2
|
||||
using Pkg
|
||||
|
||||
import PkgTemplates: badges, version_floor, substitute, read_license, gen_file, gen_readme,
|
||||
gen_tests, gen_license, gen_gitignore, gen_plugin, show_license, LICENSES,
|
||||
LICENSE_DIR, Plugin, GenericPlugin, CustomPlugin, Badge, format, interactive,
|
||||
DEFAULTS_DIR, Documenter
|
||||
|
||||
mktempdir() do temp_dir
|
||||
mkdir(joinpath(temp_dir, "dev"))
|
||||
pushfirst!(DEPOT_PATH, temp_dir)
|
||||
cd(temp_dir) do
|
||||
@testset "PkgTemplates.jl" begin
|
||||
include("tests.jl")
|
||||
end
|
||||
end
|
||||
end
|
@ -44,7 +44,7 @@ write(test_file, template_text)
|
||||
@test t.license == "MIT"
|
||||
@test t.authors == "foo"
|
||||
@test t.dir == default_dir
|
||||
@test t.julia_version == PkgTemplates.default_version()
|
||||
@test t.julia_version == PkgTemplates.default_version
|
||||
@test !t.ssh
|
||||
@test !t.manifest
|
||||
@test isempty(t.plugins)
|
||||
@ -107,7 +107,7 @@ end
|
||||
|
||||
@testset "Show methods" begin
|
||||
pkg_dir = replace(default_dir, homedir() => "~")
|
||||
ver = PkgTemplates.version_floor(PkgTemplates.default_version())
|
||||
ver = PkgTemplates.version_floor(PkgTemplates.default_version)
|
||||
buf = IOBuffer()
|
||||
t = Template(; user=me, authors="foo")
|
||||
show(buf, t)
|
||||
@ -327,12 +327,6 @@ end
|
||||
rm(temp_dir; recursive=true)
|
||||
end
|
||||
|
||||
@testset "Git-less template creation" begin
|
||||
if isempty(LibGit2.getconfig("user.name", ""))
|
||||
@test_logs Template(; user=me, git=false)
|
||||
end
|
||||
end
|
||||
|
||||
@testset "Git-less package generation" begin
|
||||
t = Template(; user=me)
|
||||
generate(test_pkg, t; git=false)
|
||||
@ -340,84 +334,6 @@ end
|
||||
@test !isfile(joinpath(t.dir, ".gitignore"))
|
||||
end
|
||||
|
||||
@testset "Version floor" begin
|
||||
@test version_floor(v"1.0.0") == "1.0"
|
||||
@test version_floor(v"1.0.1") == "1.0"
|
||||
@test version_floor(v"1.0.1-pre") == "1.0"
|
||||
@test version_floor(v"1.0.0-pre") == "1.0-"
|
||||
end
|
||||
|
||||
@testset "Mustache substitution" begin
|
||||
view = Dict{String, Any}()
|
||||
text = substitute(template_text, view)
|
||||
@test !occursin("PKGNAME: $test_pkg", text)
|
||||
@test !occursin("Documenter", text)
|
||||
@test !occursin("Codecov", text)
|
||||
@test !occursin("Coveralls", text)
|
||||
@test !occursin("After", text)
|
||||
@test !occursin("Other", text)
|
||||
view["PKGNAME"] = test_pkg
|
||||
view["OTHER"] = true
|
||||
text = substitute(template_text, view)
|
||||
@test occursin("PKGNAME: $test_pkg", text)
|
||||
@test occursin("Other", text)
|
||||
|
||||
t = Template(; user=me)
|
||||
view["OTHER"] = false
|
||||
|
||||
text = substitute(template_text, t; view=view)
|
||||
@test occursin("PKGNAME: $test_pkg", text)
|
||||
@test occursin("VERSION: $(t.julia_version.major).$(t.julia_version.minor)", text)
|
||||
@test !occursin("Documenter", text)
|
||||
@test !occursin("After", text)
|
||||
@test !occursin("Other", text)
|
||||
|
||||
t.plugins[GitHubPages] = GitHubPages()
|
||||
text = substitute(template_text, t; view=view)
|
||||
@test occursin("Documenter", text)
|
||||
@test occursin("After", text)
|
||||
empty!(t.plugins)
|
||||
|
||||
t.plugins[Codecov] = Codecov()
|
||||
text = substitute(template_text, t; view=view)
|
||||
@test occursin("Codecov", text)
|
||||
@test occursin("After", text)
|
||||
empty!(t.plugins)
|
||||
|
||||
t.plugins[Coveralls] = Coveralls()
|
||||
text = substitute(template_text, t; view=view)
|
||||
@test occursin("Coveralls", text)
|
||||
@test occursin("After", text)
|
||||
empty!(t.plugins)
|
||||
|
||||
view["OTHER"] = true
|
||||
text = substitute(template_text, t; view=view)
|
||||
@test occursin("Other", text)
|
||||
end
|
||||
|
||||
@testset "License display" begin
|
||||
io = IOBuffer()
|
||||
available_licenses(io)
|
||||
licenses = String(take!(io))
|
||||
show_license(io, "MIT")
|
||||
mit = String(take!(io))
|
||||
|
||||
# Check that all licenses are included in the display.
|
||||
for (short, long) in LICENSES
|
||||
@test occursin("$short: $long", licenses)
|
||||
end
|
||||
@test strip(mit) == strip(read_license("MIT"))
|
||||
@test strip(read_license("MIT")) == strip(read(joinpath(LICENSE_DIR, "MIT"), String))
|
||||
@test_throws ArgumentError read_license(fake_path)
|
||||
|
||||
# Check that all licenses included with the package are displayed.
|
||||
for license in readdir(LICENSE_DIR)
|
||||
@test haskey(LICENSES, license)
|
||||
end
|
||||
# Check that all licenses displayed are included with the package.
|
||||
@test length(readdir(LICENSE_DIR)) == length(LICENSES)
|
||||
end
|
||||
|
||||
@testset "Plugins" begin
|
||||
t = Template(; user=me)
|
||||
pkg_dir = joinpath(t.dir, test_pkg)
|
||||
@ -474,7 +390,8 @@ end
|
||||
warn_str = "Ignoring predefined Documenter kwargs \"format\" from additional kwargs"
|
||||
check_kwargs(kwargs, warn_str)
|
||||
|
||||
kwargs = Dict(:checkdocs => :none,
|
||||
kwargs = Dict(
|
||||
:checkdocs => :none,
|
||||
:strict => true,
|
||||
:format => :markdown,
|
||||
:stringarg => "string",
|
||||
@ -488,5 +405,3 @@ end
|
||||
end
|
||||
|
||||
include(joinpath("interactive", "interactive.jl"))
|
||||
|
||||
rm(test_file)
|
||||
|
Loading…
Reference in New Issue
Block a user