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:
|
os:
|
||||||
- linux
|
- linux
|
||||||
- osx
|
- osx
|
||||||
|
- windows
|
||||||
julia:
|
julia:
|
||||||
- 1.0
|
- 1.0
|
||||||
- 1.1
|
- 1.2
|
||||||
- nightly
|
- nightly
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
@ -12,14 +13,19 @@ matrix:
|
|||||||
fast_finish: true
|
fast_finish: true
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
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:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- stage: Documentation
|
- stage: Documentation
|
||||||
julia: 1.1
|
julia: 1.2
|
||||||
script: julia --project=docs -e '
|
script: julia --project=docs -e '
|
||||||
using Pkg;
|
using Pkg
|
||||||
Pkg.develop(PackageSpec(path=pwd()));
|
Pkg.develop(PackageSpec(; path=pwd()))
|
||||||
Pkg.instantiate();
|
Pkg.instantiate()
|
||||||
include("docs/make.jl");'
|
include("docs/make.jl")'
|
||||||
after_success: skip
|
after_success: skip
|
||||||
|
@ -3,6 +3,16 @@
|
|||||||
[[Base64]]
|
[[Base64]]
|
||||||
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
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]]
|
[[Dates]]
|
||||||
deps = ["Printf"]
|
deps = ["Printf"]
|
||||||
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||||
@ -39,9 +49,9 @@ uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
|
|||||||
|
|
||||||
[[Mustache]]
|
[[Mustache]]
|
||||||
deps = ["Printf", "Tables"]
|
deps = ["Printf", "Tables"]
|
||||||
git-tree-sha1 = "d27b8b8b99c052ea1fdd40c678bfb2dfaec4e96e"
|
git-tree-sha1 = "f39de3a12232eb47bd0629b3a661054287780276"
|
||||||
uuid = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
|
uuid = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
|
||||||
version = "0.5.12"
|
version = "0.5.13"
|
||||||
|
|
||||||
[[Pkg]]
|
[[Pkg]]
|
||||||
deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
|
deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
|
||||||
@ -59,12 +69,6 @@ uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
|
|||||||
deps = ["Serialization"]
|
deps = ["Serialization"]
|
||||||
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||||
|
|
||||||
[[Requires]]
|
|
||||||
deps = ["Test"]
|
|
||||||
git-tree-sha1 = "f6fbf4ba64d295e146e49e021207993b6b48c7d1"
|
|
||||||
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
|
|
||||||
version = "0.5.2"
|
|
||||||
|
|
||||||
[[SHA]]
|
[[SHA]]
|
||||||
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
|
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
|
||||||
|
|
||||||
@ -81,10 +85,10 @@ uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
|
|||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
||||||
[[Tables]]
|
[[Tables]]
|
||||||
deps = ["IteratorInterfaceExtensions", "LinearAlgebra", "Requires", "TableTraits", "Test"]
|
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"]
|
||||||
git-tree-sha1 = "351a4b894122e1553c6ed05fda54086ab036adef"
|
git-tree-sha1 = "aaed7b3b00248ff6a794375ad6adf30f30ca5591"
|
||||||
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
|
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
|
||||||
version = "0.2.5"
|
version = "0.2.11"
|
||||||
|
|
||||||
[[Test]]
|
[[Test]]
|
||||||
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
|
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
|
||||||
|
@ -16,7 +16,8 @@ URIParser = "30578b45-9adc-5946-b283-645ec420af67"
|
|||||||
julia = "1"
|
julia = "1"
|
||||||
|
|
||||||
[extras]
|
[extras]
|
||||||
|
Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
|
||||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||||
|
|
||||||
[targets]
|
[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
|
# Documentation: https://github.com/JuliaCI/Appveyor.jl
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- julia_version: {{VERSION}}
|
{{#VERSIONS}}
|
||||||
- julia_version: nightly
|
- julia_version: {{.}}
|
||||||
|
{{/VERSIONS}}
|
||||||
platform:
|
platform:
|
||||||
- x86
|
{{#PLATFORMS}}
|
||||||
- x64
|
- {{.}}
|
||||||
|
{{/PLATFORMS}}
|
||||||
|
{{#HAS_NIGHTLY}}
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- julia_version: nightly
|
- julia_version: nightly
|
||||||
|
{{/HAS_NIGHTLY}}
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
@ -26,8 +30,8 @@ build_script:
|
|||||||
test_script:
|
test_script:
|
||||||
- echo "%JL_TEST_SCRIPT%"
|
- echo "%JL_TEST_SCRIPT%"
|
||||||
- C:\julia\bin\julia -e "%JL_TEST_SCRIPT%"
|
- C:\julia\bin\julia -e "%JL_TEST_SCRIPT%"
|
||||||
{{#CODECOV}}
|
{{#HAS_CODECOV}}
|
||||||
on_success:
|
on_success:
|
||||||
- echo "%JL_CODECOV_SCRIPT%"
|
- echo "%JL_CODECOV_SCRIPT%"
|
||||||
- C:\julia\bin\julia -e "%JL_CODECOV_SCRIPT%"
|
- C:\julia\bin\julia -e "%JL_CODECOV_SCRIPT%"
|
||||||
{{/CODECOV}}
|
{{/HAS_CODECOV}}
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
freebsd_instance:
|
freebsd_instance:
|
||||||
image: freebsd-12-0-release-amd64
|
image: {{IMAGE}}
|
||||||
task:
|
task:
|
||||||
name: FreeBSD
|
name: FreeBSD
|
||||||
env:
|
env:
|
||||||
JULIA_VERSION: {{VERSION}}
|
{{#VERSIONS}}
|
||||||
|
JULIA_VERSION: {{.}}
|
||||||
|
{{/VERSIONS}}
|
||||||
install_script:
|
install_script:
|
||||||
- sh -c "$(fetch https://raw.githubusercontent.com/ararslan/CirrusCI.jl/master/bin/install.sh -o -)"
|
- sh -c "$(fetch https://raw.githubusercontent.com/ararslan/CirrusCI.jl/master/bin/install.sh -o -)"
|
||||||
build_script:
|
build_script:
|
||||||
- cirrusjl build
|
- cirrusjl build
|
||||||
test_script:
|
test_script:
|
||||||
- cirrusjl test
|
- cirrusjl test
|
||||||
{{#COVERAGE}}
|
{{#HAS_COVERAGE}}
|
||||||
coverage_script:
|
coverage_script:
|
||||||
- cirrusjl coverage{{#CODECOV}} codecov{{/CODECOV}}{{#COVERALLS}} coveralls{{/COVERALLS}}
|
- cirrusjl coverage{{#HAS_CODECOV}} codecov{{/HAS_CODECOV}}{{#HAS_COVERALLS}} coveralls{{/HAS_COVERALLS}}
|
||||||
{{/COVERAGE}}
|
{{/HAS_COVERAGE}}
|
||||||
|
@ -1,19 +1,30 @@
|
|||||||
Julia {{VERSION}}:
|
{{#VERSIONS}}
|
||||||
image: julia:{{VERSION}}
|
Julia {{.}}:
|
||||||
script: julia --project='@.' -e 'using Pkg; Pkg.build(); Pkg.test({{#GITLABCOVERAGE}}; coverage=true{{/GITLABCOVERAGE}})'
|
image: julia:{{.}}
|
||||||
{{#GITLABCOVERAGE}}
|
script: julia --project=@. -e '
|
||||||
|
using Pkg
|
||||||
|
Pkg.build()
|
||||||
|
Pkg.test({{#HAS_COVERAGE}}coverage=true{{/HAS_COVERAGE}})'
|
||||||
|
{{/VERSIONS}}
|
||||||
|
{{#HAS_COVERAGE}}
|
||||||
coverage: /Test Coverage (\d+\.\d+%)/
|
coverage: /Test Coverage (\d+\.\d+%)/
|
||||||
after_script:
|
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'
|
- julia -e '
|
||||||
{{/GITLABCOVERAGE}}
|
using Pkg
|
||||||
{{#DOCUMENTER}}
|
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:
|
pages:
|
||||||
image: julia:{{VERSION}}
|
image: julia:{{VERSION}}
|
||||||
stage: deploy
|
stage: deploy
|
||||||
script:
|
script:
|
||||||
- julia --project=docs -e '
|
- julia --project=docs -e '
|
||||||
using Pkg;
|
using Pkg;
|
||||||
Pkg.develop(PackageSpec(path=pwd()));
|
Pkg.develop(PackageSpec(; path=pwd()));
|
||||||
Pkg.instantiate();
|
Pkg.instantiate();
|
||||||
include("docs/make.jl");'
|
include("docs/make.jl");'
|
||||||
- mkdir -p public
|
- mkdir -p public
|
||||||
@ -23,4 +34,4 @@ pages:
|
|||||||
- public
|
- public
|
||||||
only:
|
only:
|
||||||
- master
|
- 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
|
language: julia
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
julia:
|
|
||||||
- {{VERSION}}
|
|
||||||
- nightly
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- julia: nightly
|
|
||||||
fast_finish: true
|
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
{{#COVERAGE}}
|
{{#HAS_DOCUMENTER}}
|
||||||
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}}
|
|
||||||
jobs:
|
jobs:
|
||||||
|
fast_finish: true
|
||||||
|
{{#HAS_NIGHTLY}}
|
||||||
|
allow_failures:
|
||||||
|
- julia: nightly
|
||||||
|
{{/HAS_NIGHTLY}}
|
||||||
include:
|
include:
|
||||||
|
{{#JOBS}}
|
||||||
|
- julia: {{JULIA}}
|
||||||
|
os: {{OS}}
|
||||||
|
{{#ARCH}}
|
||||||
|
arch: {{ARCH}}
|
||||||
|
{{/ARCH}}
|
||||||
|
{{/JOBS}}
|
||||||
|
{{#HAS_DOCUMENTER}}
|
||||||
- stage: Documentation
|
- stage: Documentation
|
||||||
julia: {{VERSION}}
|
julia: {{VERSION}}
|
||||||
script: julia --project=docs -e '
|
script: julia --project=docs -e '
|
||||||
using Pkg;
|
using Pkg;
|
||||||
Pkg.develop(PackageSpec(path=pwd()));
|
Pkg.develop(PackageSpec(; path=pwd()));
|
||||||
Pkg.instantiate();
|
Pkg.instantiate();
|
||||||
include("docs/make.jl");'
|
include("docs/make.jl");'
|
||||||
after_success: skip
|
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]]
|
[[Base64]]
|
||||||
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||||
|
|
||||||
@ -6,35 +8,34 @@ deps = ["Printf"]
|
|||||||
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||||
|
|
||||||
[[Distributed]]
|
[[Distributed]]
|
||||||
deps = ["LinearAlgebra", "Random", "Serialization", "Sockets"]
|
deps = ["Random", "Serialization", "Sockets"]
|
||||||
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
|
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
|
||||||
|
|
||||||
[[DocStringExtensions]]
|
[[DocStringExtensions]]
|
||||||
deps = ["LibGit2", "Markdown", "Pkg", "Test"]
|
deps = ["LibGit2", "Markdown", "Pkg", "Test"]
|
||||||
git-tree-sha1 = "1df01539a1c952cef21f2d2d1c092c2bcf0177d7"
|
git-tree-sha1 = "0513f1a8991e9d83255e0140aace0d0fc4486600"
|
||||||
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
|
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
|
||||||
version = "0.6.0"
|
version = "0.8.0"
|
||||||
|
|
||||||
[[Documenter]]
|
[[Documenter]]
|
||||||
deps = ["Base64", "DocStringExtensions", "InteractiveUtils", "LibGit2", "Logging", "Markdown", "Pkg", "REPL", "Random", "Test", "Unicode"]
|
deps = ["Base64", "DocStringExtensions", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"]
|
||||||
git-tree-sha1 = "a6db1c69925cdc53aafb38caec4446be26e0c617"
|
git-tree-sha1 = "c61d6eedbc3c4323c08b64af12d29c8ee0fcbb5f"
|
||||||
uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
|
uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
|
||||||
version = "0.21.0"
|
version = "0.23.2"
|
||||||
|
|
||||||
[[InteractiveUtils]]
|
[[InteractiveUtils]]
|
||||||
deps = ["LinearAlgebra", "Markdown"]
|
deps = ["Markdown"]
|
||||||
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
|
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]]
|
[[LibGit2]]
|
||||||
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
|
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
|
||||||
|
|
||||||
[[Libdl]]
|
|
||||||
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
|
|
||||||
|
|
||||||
[[LinearAlgebra]]
|
|
||||||
deps = ["Libdl"]
|
|
||||||
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
|
||||||
|
|
||||||
[[Logging]]
|
[[Logging]]
|
||||||
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
||||||
|
|
||||||
@ -42,6 +43,15 @@ uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
|||||||
deps = ["Base64"]
|
deps = ["Base64"]
|
||||||
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
|
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]]
|
[[Pkg]]
|
||||||
deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
|
deps = ["Dates", "LibGit2", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
|
||||||
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
|
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
|
||||||
@ -72,7 +82,7 @@ deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
|
|||||||
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||||
|
|
||||||
[[UUIDs]]
|
[[UUIDs]]
|
||||||
deps = ["Random"]
|
deps = ["Random", "SHA"]
|
||||||
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
||||||
|
|
||||||
[[Unicode]]
|
[[Unicode]]
|
||||||
|
@ -72,8 +72,7 @@ t = Template(;
|
|||||||
Codecov(),
|
Codecov(),
|
||||||
Coveralls(),
|
Coveralls(),
|
||||||
AppVeyor(),
|
AppVeyor(),
|
||||||
GitHubPages(),
|
Documenter{TravisCI}(),
|
||||||
CirrusCI(),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
generate("MyPkg2", t)
|
generate("MyPkg2", t)
|
||||||
@ -103,5 +102,4 @@ include, you are encouraged to use [AttoBot](https://github.com/apps/attobot) in
|
|||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
It's extremely easy to extend `PkgTemplates` with new plugins. To get started,
|
It's extremely easy to extend `PkgTemplates` with new plugins. To get started,
|
||||||
check out the
|
check out [Plugin Development](@ref).
|
||||||
[plugin development guide](https://invenia.github.io/PkgTemplates.jl/stable/pages/plugin_development.html).
|
|
||||||
|
@ -4,17 +4,11 @@ CurrentModule = PkgTemplates
|
|||||||
|
|
||||||
# Licenses
|
# Licenses
|
||||||
|
|
||||||
[Many open-source licenses](https://github.com/christopher-dG/PkgTemplates.jl/tree/master/licenses)
|
[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,
|
are available for use with `PkgTemplates`, but if you see that one is missing, don't
|
||||||
don't hesitate to open an issue or PR.
|
hesitate to open an issue or PR.
|
||||||
|
|
||||||
```@docs
|
```@docs
|
||||||
available_licenses
|
available_licenses
|
||||||
show_license
|
show_license
|
||||||
```
|
```
|
||||||
|
|
||||||
### Helper Functions
|
|
||||||
|
|
||||||
```@docs
|
|
||||||
read_license
|
|
||||||
```
|
|
||||||
|
@ -7,25 +7,9 @@ CurrentModule = PkgTemplates
|
|||||||
Creating new packages with `PkgTemplates` revolves around creating a new
|
Creating new packages with `PkgTemplates` revolves around creating a new
|
||||||
[`Template`](@ref), then calling [`generate`](@ref) on it.
|
[`Template`](@ref), then calling [`generate`](@ref) on it.
|
||||||
|
|
||||||
## `Template`
|
|
||||||
|
|
||||||
```@docs
|
```@docs
|
||||||
Template
|
Template
|
||||||
interactive_template
|
interactive_template
|
||||||
```
|
|
||||||
|
|
||||||
## `generate`
|
|
||||||
|
|
||||||
```@docs
|
|
||||||
generate
|
generate
|
||||||
generate_interactive
|
generate_interactive
|
||||||
```
|
```
|
||||||
|
|
||||||
### Helper Functions
|
|
||||||
|
|
||||||
```@docs
|
|
||||||
gen_tests
|
|
||||||
gen_readme
|
|
||||||
gen_gitignore
|
|
||||||
gen_license
|
|
||||||
```
|
|
||||||
|
@ -4,72 +4,69 @@ CurrentModule = PkgTemplates
|
|||||||
|
|
||||||
# Plugin Development
|
# Plugin Development
|
||||||
|
|
||||||
The best and easiest way to contribute to `PkgTemplates` is to write new
|
The best and easiest way to contribute to `PkgTemplates` is to write new plugins.
|
||||||
plugins.
|
|
||||||
|
|
||||||
```@docs
|
```@docs
|
||||||
Plugin
|
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
|
```@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
|
## Custom Plugins
|
||||||
|
|
||||||
```@docs
|
When a plugin is too complicated to be expressed with [`GeneratedPlugin`](@ref), we only
|
||||||
CustomPlugin
|
need to implement a few methods to create something fully custom.
|
||||||
```
|
|
||||||
|
|
||||||
### `CustomPlugin` Required Methods
|
### Required Methods
|
||||||
|
|
||||||
#### `gen_plugin`
|
|
||||||
|
|
||||||
```@docs
|
```@docs
|
||||||
gen_plugin
|
gen_plugin
|
||||||
|
```
|
||||||
|
|
||||||
|
### Optional Methods
|
||||||
|
|
||||||
|
```@docs
|
||||||
interactive
|
interactive
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: [`interactive`](@ref) is not strictly required, however without it,
|
Additionally, [`gitignore`](@ref), [`badges`](@ref), and [`view`](@ref) can also be
|
||||||
your custom plugin will not be available when creating templates with
|
implemented in the same way as for [`GeneratedPlugin`](@ref)s (they have empty default
|
||||||
[`interactive_template`](@ref).
|
implementations). [`source`](@ref) and [`destination`](@ref) have no meaning for custom
|
||||||
|
plugins.
|
||||||
|
|
||||||
#### `badges`
|
### Helpers
|
||||||
|
|
||||||
```@docs
|
These types and functions will make implementing the above methods much easier.
|
||||||
badges
|
|
||||||
```
|
|
||||||
|
|
||||||
## Helper Types/Functions
|
|
||||||
|
|
||||||
#### `gen_file`
|
|
||||||
|
|
||||||
```@docs
|
|
||||||
gen_file
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `substitute`
|
|
||||||
|
|
||||||
```@docs
|
|
||||||
substitute
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `Badge`
|
|
||||||
|
|
||||||
```@docs
|
```@docs
|
||||||
Badge
|
Badge
|
||||||
```
|
gen_file
|
||||||
|
substitute
|
||||||
#### `format`
|
|
||||||
|
|
||||||
```@docs
|
|
||||||
format
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `version_floor`
|
|
||||||
|
|
||||||
```@docs
|
|
||||||
version_floor
|
version_floor
|
||||||
```
|
```
|
||||||
|
@ -28,6 +28,4 @@ Coveralls
|
|||||||
|
|
||||||
```@docs
|
```@docs
|
||||||
Documenter
|
Documenter
|
||||||
GitHubPages
|
|
||||||
GitLabPages
|
|
||||||
```
|
```
|
||||||
|
@ -1,36 +1,34 @@
|
|||||||
module PkgTemplates
|
module PkgTemplates
|
||||||
|
|
||||||
using Dates
|
using Base: @kwdef, current_project
|
||||||
using InteractiveUtils
|
using Base.Filesystem: contractuser
|
||||||
using LibGit2
|
using Dates: month, today, year
|
||||||
using Mustache
|
using InteractiveUtils: subtypes
|
||||||
using Pkg
|
using LibGit2: LibGit2
|
||||||
using REPL.TerminalMenus
|
using Mustache: render
|
||||||
using URIParser
|
using Pkg: PackageSpec, Pkg
|
||||||
|
using REPL.TerminalMenus: MultiSelectMenu, RadioMenu, request
|
||||||
|
using URIParser: URI
|
||||||
|
|
||||||
export
|
export
|
||||||
# Template/package generation.
|
|
||||||
Template,
|
Template,
|
||||||
generate,
|
|
||||||
interactive_template,
|
|
||||||
generate_interactive,
|
|
||||||
# Licenses.
|
|
||||||
show_license,
|
|
||||||
available_licenses,
|
|
||||||
# Plugins.
|
|
||||||
GitHubPages,
|
|
||||||
GitLabPages,
|
|
||||||
AppVeyor,
|
AppVeyor,
|
||||||
TravisCI,
|
|
||||||
GitLabCI,
|
|
||||||
CirrusCI,
|
CirrusCI,
|
||||||
|
Citation,
|
||||||
Codecov,
|
Codecov,
|
||||||
Coveralls,
|
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.
|
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
|
abstract type Plugin end
|
||||||
|
|
||||||
@ -38,18 +36,6 @@ include("licenses.jl")
|
|||||||
include("template.jl")
|
include("template.jl")
|
||||||
include("generate.jl")
|
include("generate.jl")
|
||||||
include("plugin.jl")
|
include("plugin.jl")
|
||||||
include(joinpath("plugins", "documenter.jl"))
|
include("interactive.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]
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
336
src/generate.jl
336
src/generate.jl
@ -1,16 +1,12 @@
|
|||||||
"""
|
const TEST_UUID = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||||
generate(pkg::AbstractString, t::Template) -> Nothing
|
|
||||||
generate(t::Template, pkg::AbstractString) -> Nothing
|
|
||||||
|
|
||||||
Generate a package named `pkg` from `t`. If `git` is `false`, no Git repository is created.
|
|
||||||
"""
|
"""
|
||||||
function generate(
|
(::Template)(pkg::AbstractString)
|
||||||
pkg::AbstractString,
|
|
||||||
t::Template;
|
Generate a package named `pkg` from a [`Template`](@ref).
|
||||||
git::Bool=true,
|
"""
|
||||||
gitconfig::Union{GitConfig, Nothing}=nothing,
|
function (t::Template)(pkg::AbstractString)
|
||||||
)
|
endswith(pkg, ".jl") && (pkg = pkg[1:end-3])
|
||||||
pkg = splitjl(pkg)
|
|
||||||
pkg_dir = joinpath(t.dir, pkg)
|
pkg_dir = joinpath(t.dir, pkg)
|
||||||
ispath(pkg_dir) && throw(ArgumentError("$pkg_dir already exists"))
|
ispath(pkg_dir) && throw(ArgumentError("$pkg_dir already exists"))
|
||||||
|
|
||||||
@ -18,9 +14,9 @@ function generate(
|
|||||||
# Create the directory with some boilerplate inside.
|
# Create the directory with some boilerplate inside.
|
||||||
Pkg.generate(pkg_dir)
|
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
|
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
|
end
|
||||||
|
|
||||||
# Replace the authors field with the template's authors.
|
# Replace the authors field with the template's authors.
|
||||||
@ -31,329 +27,35 @@ function generate(
|
|||||||
write(path, replace(project, r"authors = .*" => "authors = $authors"))
|
write(path, replace(project, r"authors = .*" => "authors = $authors"))
|
||||||
end
|
end
|
||||||
|
|
||||||
if git
|
if t.git
|
||||||
# Initialize the repo.
|
# Initialize the repo, make a commit, and set the remote.
|
||||||
repo = LibGit2.init(pkg_dir)
|
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")
|
LibGit2.commit(repo, "Initial commit")
|
||||||
rmt = if t.ssh
|
rmt = if t.ssh
|
||||||
"git@$(t.host):$(t.user)/$pkg.jl.git"
|
"git@$(t.host):$(t.user)/$pkg.jl.git"
|
||||||
else
|
else
|
||||||
"https://$(t.host)/$(t.user)/$pkg.jl"
|
"https://$(t.host)/$(t.user)/$pkg.jl"
|
||||||
end
|
end
|
||||||
# We need to set the remote in a strange way, see #8.
|
|
||||||
close(LibGit2.GitRemote(repo, "origin", rmt))
|
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
|
end
|
||||||
|
|
||||||
# Generate the files.
|
# Generate the files.
|
||||||
files = vcat(
|
foreach(p -> gen_plugin(p, t, pkg_dir), values(t.plugins))
|
||||||
"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))...),
|
|
||||||
)
|
|
||||||
|
|
||||||
if git
|
if t.git
|
||||||
append!(files, gen_gitignore(pkg_dir, t))
|
# Commit the files.
|
||||||
LibGit2.add!(repo, files...)
|
LibGit2.add!(repo, ".")
|
||||||
LibGit2.commit(repo, "Files generated by PkgTemplates")
|
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
|
end
|
||||||
|
|
||||||
if t.dev
|
if t.dev
|
||||||
# Add the new package to the current environment.
|
# Add the new package to the current environment.
|
||||||
Pkg.develop(PackageSpec(path=pkg_dir))
|
Pkg.develop(PackageSpec(; path=pkg_dir))
|
||||||
end
|
end
|
||||||
|
|
||||||
@info "New package is at $pkg_dir"
|
@info "New package is at $pkg_dir"
|
||||||
catch e
|
catch
|
||||||
rm(pkg_dir; recursive=true)
|
rm(pkg_dir; recursive=true, force=true)
|
||||||
rethrow(e)
|
rethrow()
|
||||||
end
|
end
|
||||||
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 @@
|
|||||||
"""
|
const DEFAULTS_DIR = normpath(joinpath(@__DIR__, "..", "defaults"))
|
||||||
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.
|
|
||||||
|
|
||||||
# Attributes
|
abstract type BasicPlugin <: Plugin end
|
||||||
* `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.
|
|
||||||
|
|
||||||
# Example
|
default_file(paths::AbstractString...) = joinpath(DEFAULTS_DIR, paths...)
|
||||||
```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
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Custom plugins are plugins whose behaviour does not follow the [`GenericPlugin`](@ref)
|
view(::Plugin, ::Template, pkg::AbstractString) -> Dict{String}
|
||||||
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.
|
|
||||||
|
|
||||||
# Attributes
|
Return extra string substitutions to be made for this plugin.
|
||||||
* `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.
|
|
||||||
"""
|
"""
|
||||||
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
|
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.
|
* `hover::AbstractString`: Text to appear when the mouse is hovered over the badge.
|
||||||
* `image::AbstractString`: URL to the image to display.
|
* `image::AbstractString`: URL to the image to display.
|
||||||
* `link::AbstractString`: URL to go to upon clicking the badge.
|
* `link::AbstractString`: URL to go to upon clicking the badge.
|
||||||
@ -158,89 +56,70 @@ struct Badge
|
|||||||
link::String
|
link::String
|
||||||
end
|
end
|
||||||
|
|
||||||
"""
|
Base.string(b::Badge) = "[)]($(b.link))"
|
||||||
format(b::Badge) -> String
|
|
||||||
|
|
||||||
Return `badge`'s data formatted as a Markdown string.
|
# Format a plugin's badges as a list of strings, with all substitutions applied.
|
||||||
"""
|
function badges(p::Plugin, t::Template, pkg_name::AbstractString)
|
||||||
format(b::Badge) = "[)]($(b.link))"
|
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.
|
Generate any files associated with a plugin.
|
||||||
|
|
||||||
# Arguments
|
## Arguments
|
||||||
* `p::Plugin`: Plugin whose files are being generated.
|
* `p::Plugin`: Plugin whose files are being generated.
|
||||||
* `t::Template`: Template configuration.
|
* `t::Template`: Template configuration.
|
||||||
* `pkg_name::AbstractString`: Name of the package.
|
* `pkg::AbstractString`: Name of the package.
|
||||||
|
|
||||||
Returns an array of generated file/directory names.
|
|
||||||
"""
|
"""
|
||||||
gen_plugin(::Plugin, ::Template, ::AbstractString) = String[]
|
gen_plugin(::Plugin, ::Template, ::AbstractString) = nothing
|
||||||
|
|
||||||
function gen_plugin(p::GenericPlugin, t::Template, pkg_name::AbstractString)
|
function gen_plugin(p::BasicPlugin, t::Template, pkg::AbstractString)
|
||||||
if p.src === nothing
|
source(p) === nothing && return
|
||||||
return String[]
|
text = render(source(p), view(p, t, pkg); tags=tags(p))
|
||||||
end
|
gen_file(joinpath(t.dir, pkg_name, destination(p)), text)
|
||||||
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]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
"""
|
"""
|
||||||
badges(p::Plugin, user::AbstractString, pkg_name::AbstractString) -> Vector{String}
|
gen_file(file::AbstractString, text::AbstractString) -> Int
|
||||||
|
|
||||||
Generate Markdown badges for the plugin.
|
Create a new file containing some given text.
|
||||||
|
Trailing whitespace is removed, and the file will end with a newline.
|
||||||
# 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.
|
|
||||||
"""
|
"""
|
||||||
badges(::Plugin, ::AbstractString, ::AbstractString) = String[]
|
function gen_file(file::AbstractString, text::AbstractString)
|
||||||
|
mkpath(dirname(file))
|
||||||
function badges(p::GenericPlugin, user::AbstractString, pkg_name::AbstractString)
|
text = join(map(rstrip, split(text, "\n")), "\n")
|
||||||
# Give higher priority to replacements defined in the plugin's view.
|
endswith(text , "\n") || (text *= "\n")
|
||||||
view = merge(Dict("USER" => user, "PKGNAME" => pkg_name), p.view)
|
write(file, text)
|
||||||
return map(b -> substitute(format(b), view), p.badges)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
"""
|
render_file(file::AbstractString, view, tags) = render_text(read(file, String), view, tags)
|
||||||
interactive(T::Type{<:Plugin}; file::Union{AbstractString, Nothing}="") -> Plugin
|
|
||||||
|
|
||||||
Interactively create a plugin of type `T`, where `file` is the plugin type's default
|
render_text(text::AbstractString, view, tags) = render(text, view; tags=tags)
|
||||||
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)
|
|
||||||
|
|
||||||
print("$name: Enter the config template filename (\"None\" for no file) ")
|
function render_badges(p::BasicPlugin, t::Template, pkg::AbstractString)
|
||||||
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)
|
|
||||||
end
|
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
|
Add `Citation` to a [`Template`](@ref)'s plugin list to generate a `CITATION.bib` file.
|
||||||
generated repositories, and an appropriate section in the README.
|
If `readme` is set, then `README.md` will contain a section about citing.
|
||||||
|
|
||||||
# Keyword Arguments:
|
|
||||||
* `readme_section::Bool=false`: whether to add a section in the readme pointing to `CITATION.bib`.
|
|
||||||
"""
|
"""
|
||||||
struct Citation <: GenericPlugin
|
@kwdef struct Citation <: BasicPlugin
|
||||||
gitignore::Vector{AbstractString}
|
file::String = default_file("CITATION.bib")
|
||||||
src::Union{String, Nothing}
|
readme::Bool = false
|
||||||
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
|
|
||||||
end
|
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})
|
function interactive(::Type{Citation})
|
||||||
print("Citation: Add a section to README.md mentioning CITATION.bib? [no]: ")
|
readme = prompt_bool("Citation: Add a section to the README", false)
|
||||||
readme = uppercase(readline()) in ["Y", "YES", "TRUE"]
|
|
||||||
return Citation(; readme_section=readme)
|
return Citation(; readme_section=readme)
|
||||||
end
|
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 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
|
Documenter{T<:Union{TravisCI, GitLabCI, Nothing}}(;
|
||||||
generation via [Documenter.jl](https://github.com/JuliaDocs/Documenter.jl).
|
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
|
The `Documenter` plugin adds support for documentation generation via [Documenter.jl](https://github.com/JuliaDocs/Documenter.jl).
|
||||||
file contains the Documenter.makedocs command with predefined values for `modules`,
|
Documentation deployment depends on `T`, where `T` is some supported CI plugin, or `Nothing` to only support local documentation builds.
|
||||||
`format`, `pages`, `repo`, `sitename`, and `authors`.
|
|
||||||
|
|
||||||
The subtype is expected to include the following fields:
|
## Keyword Arguments
|
||||||
* `assets::Vector{AbstractString}`, a list of filenames to be included as the `assets`
|
todo
|
||||||
kwarg to `makedocs`
|
- `assets::Vector{<:AbstractString}=String[]`:
|
||||||
* `gitignore::Vector{AbstractString}`, a list of files to be added to the `.gitignore`
|
- `makedocs_kwargs::Dict{Symbol}=Dict{Symbol, Any}()`:
|
||||||
|
- `canonical_url::Union{Function, Nothing}=nothing`:`
|
||||||
|
|
||||||
It may optionally include the field `additional_kwargs::Union{AbstractDict, NamedTuple}`
|
!!! note
|
||||||
to allow additional kwargs to be added to `makedocs`.
|
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)
|
# Can't use @kwdef due to some weird precompilation issues.
|
||||||
path = joinpath(t.dir, pkg_name)
|
function Documenter{T}(
|
||||||
docs_dir = joinpath(path, "docs")
|
assets::Vector{<:AbstractString}=String[],
|
||||||
mkpath(docs_dir)
|
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.
|
# Create the documentation project.
|
||||||
proj = Base.current_project()
|
docs_dir = joinpath(pkg_dir, "docs")
|
||||||
|
proj = current_project()
|
||||||
try
|
try
|
||||||
Pkg.activate(docs_dir)
|
Pkg.activate(docs_dir)
|
||||||
Pkg.add(PackageSpec(; name="Documenter", uuid=DOCUMENTER_UUID))
|
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)
|
proj === nothing ? Pkg.activate() : Pkg.activate(proj)
|
||||||
end
|
end
|
||||||
|
|
||||||
tab = repeat(" ", 4)
|
# Copy any assets.
|
||||||
assets_string = if !isempty(p.assets)
|
assets_dir = joinpath(docs_dir, "src", "assets")
|
||||||
mkpath(joinpath(docs_dir, "src", "assets"))
|
isempty(p.assets) || mkpath(assets_dir)
|
||||||
for file in p.assets
|
foreach(a -> cp(a, joinpath(assets_dir, basename(asset))), 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)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Base.show(io::IO, p::Documenter)
|
function interactive(::Type{Documenter{T}}) where T
|
||||||
spc = " "
|
name = "Documenter{$T}"
|
||||||
println(io, nameof(typeof(p)), ":")
|
|
||||||
|
|
||||||
n = length(p.assets)
|
print("$name: Enter any Documenter asset files (separated by spaces) [none]: ")
|
||||||
s = n == 1 ? "" : "s"
|
assets = split(readline())
|
||||||
print(io, spc, "→ $n asset file$s")
|
|
||||||
if n == 0
|
print("$name: Enter any extra makedocs key-value pairs (joined by '=') [none]\n> ")
|
||||||
println(io)
|
kwargs = Dict{Symbol, Any}()
|
||||||
else
|
line = map(split(readline())) do kv
|
||||||
println(io, ": ", join(map(a -> replace(a, homedir() => "~"), p.assets), ", "))
|
k, v = split(kv, "="; limit=2)
|
||||||
|
kwargs[Symbol(k)] = eval(Meta.parse(v))
|
||||||
end
|
end
|
||||||
|
|
||||||
n = length(p.gitignore)
|
return Documenter{T}(; assets=assets, kwargs=kwargs)
|
||||||
s = n == 1 ? "" : "s"
|
|
||||||
print(io, "$spc→ $n gitignore entrie$s")
|
|
||||||
n > 0 && print(io, ": ", join(map(repr, p.gitignore), ", "))
|
|
||||||
end
|
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)
|
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
|
Records common information used to generate a package.
|
||||||
create a template, you can use [`interactive_template`](@ref) instead.
|
|
||||||
|
|
||||||
# Keyword Arguments
|
## Keyword Arguments
|
||||||
* `user::AbstractString=""`: GitHub (or other code hosting service) username. If left
|
- `user::AbstractString=""`: GitHub (or other code hosting service) username.
|
||||||
unset, it will take the the global git config's value (`github.user`). If that is not
|
If left unset, it will take the the global Git config's value (`github.user`).
|
||||||
set, an `ArgumentError` is thrown. **This is case-sensitive for some plugins, so take
|
If that is not set, an `ArgumentError` is thrown.
|
||||||
care to enter it correctly.**
|
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
|
- `host::AbstractString="github.com"`: URL to the code hosting service where your package will reside.
|
||||||
will reside. Note that while hosts other than GitHub won't cause errors, they are not
|
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.
|
||||||
officially supported and they will cause certain plugins will produce incorrect output.
|
- `authors::Union{AbstractString, Vector{<:AbstractString}}=""`: Names that appear on the license.
|
||||||
* `license::AbstractString="MIT"`: Name of the package license. If an empty string is
|
Supply a string for one author or an array for multiple.
|
||||||
given, no license is created. [`available_licenses`](@ref) can be used to list all
|
Similarly to `user`, it will take the value of of the global Git config's value if it is left unset.
|
||||||
available licenses, and [`show_license`](@ref) can be used to print out a particular
|
- `dir::AbstractString=$(contractuser(Pkg.devdir()))`: Directory in which the package will go.
|
||||||
license's text.
|
Relative paths are converted to absolute ones at template creation time.
|
||||||
* `authors::Union{AbstractString, Vector{<:AbstractString}}=""`: Names that appear on the
|
- `julia_version::VersionNumber=$DEFAULT_VERSION`: Minimum allowed Julia version.
|
||||||
license. Supply a string for one author or an array for multiple. Similarly to `user`,
|
- `ssh::Bool=false`: Whether or not to use SSH for the git remote. If `false` HTTPS will be used.
|
||||||
it will take the value of of the global git config's value if it is left unset.
|
- `manifest::Bool=false`: Whether or not to commit the `Manifest.toml`.
|
||||||
* `dir::AbstractString=$(replace(Pkg.devdir(), homedir() => "~"))`: Directory in which the
|
- `git::Bool=true`: Whether or not to create a Git repository for generated packages.
|
||||||
package will go. Relative paths are converted to absolute ones at template creation time.
|
- `develop::Bool=true`: Whether or not to `develop` generated packages in the active environment.
|
||||||
* `julia_version::VersionNumber=$(default_version())`: Minimum allowed Julia version.
|
- `plugins::Vector{<:Plugin}=Plugin[]`: A list of plugins that the package will include.
|
||||||
* `ssh::Bool=false`: Whether or not to use SSH for the git remote. If `false` HTTPS will be used.
|
- `disable_default_plugins::Vector{DataType}=DataType[]`: Default plugins to disable.
|
||||||
* `dev::Bool=true`: Whether or not to `Pkg.develop` generated packages.
|
The default plugins are [`Readme`](@ref), [`License`](@ref), [`Tests`](@ref), and [`Gitignore`](@ref).
|
||||||
* `manifest::Bool=false`: Whether or not to commit the `Manifest.toml`.
|
To override a default plugin instead of disabling it altogether, supply it via `plugins`.
|
||||||
* `plugins::Vector{<:Plugin}=Plugin[]`: A list of `Plugin`s that the package will include.
|
- `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
|
struct Template
|
||||||
user::String
|
user::String
|
||||||
host::String
|
host::String
|
||||||
license::String
|
|
||||||
authors::String
|
authors::String
|
||||||
dir::String
|
dir::String
|
||||||
julia_version::VersionNumber
|
julia_version::VersionNumber
|
||||||
ssh::Bool
|
ssh::Bool
|
||||||
dev::Bool
|
|
||||||
manifest::Bool
|
manifest::Bool
|
||||||
|
git::Bool
|
||||||
|
develop::Bool
|
||||||
plugins::Dict{DataType, <:Plugin}
|
plugins::Dict{DataType, <:Plugin}
|
||||||
|
end
|
||||||
|
|
||||||
function Template(;
|
Template(; interactive::Bool=false, kwargs...) = make_template(Val(interactive); kwargs...)
|
||||||
user::AbstractString="",
|
|
||||||
host::AbstractString="https://github.com",
|
function make_template(::Val{false}; kwargs...)
|
||||||
license::AbstractString="MIT",
|
user = getkw(kwargs, :user)
|
||||||
authors::Union{AbstractString, Vector{<:AbstractString}}="",
|
if isempty(user)
|
||||||
dir::AbstractString=Pkg.devdir(),
|
throw(ArgumentError("No username found, set one with user=username"))
|
||||||
julia_version::VersionNumber=default_version(),
|
end
|
||||||
ssh::Bool=false,
|
|
||||||
dev::Bool=true,
|
host = getkw(kwargs, :host)
|
||||||
manifest::Bool=false,
|
host = URI(occursin("://", host) ? host : "https://$host").host
|
||||||
plugins::Vector{<:Plugin}=Plugin[],
|
|
||||||
git::Bool=true,
|
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
|
end
|
||||||
|
|
||||||
function Base.show(io::IO, t::Template)
|
hasplugin(t::Template, ::Type{T}) where T <: Plugin = any(U -> U <: T, keys(t.plugins))
|
||||||
maybe(s::String) = isempty(s) ? "None" : s
|
|
||||||
spc = " "
|
|
||||||
|
|
||||||
println(io, "Template:")
|
getkw(kwargs, k) = get(() -> defaultkw(k), kwargs, k)
|
||||||
println(io, spc, "→ User: ", maybe(t.user))
|
|
||||||
println(io, spc, "→ Host: ", maybe(t.host))
|
|
||||||
|
|
||||||
print(io, spc, "→ License: ")
|
defaultkw(s::Symbol) = defaultkw(Val(s))
|
||||||
if isempty(t.license)
|
defaultkw(::Val{:user}) = LibGit2.getconfig("github.user", "")
|
||||||
println(io, "None")
|
defaultkw(::Val{:host}) = "https://github.com"
|
||||||
else
|
defaultkw(::Val{:dir}) = Pkg.devdir()
|
||||||
println(io, t.license, " ($(t.authors) ", year(today()), ")")
|
defaultkw(::Val{:julia_version}) = DEFAULT_VERSION
|
||||||
end
|
defaultkw(::Val{:ssh}) = false
|
||||||
|
defaultkw(::Val{:manifest}) = false
|
||||||
println(io, spc, "→ Package directory: ", replace(maybe(t.dir), homedir() => "~"))
|
defaultkw(::Val{:git}) = true
|
||||||
println(io, spc, "→ Minimum Julia version: v", version_floor(t.julia_version))
|
defaultkw(::Val{:develop}) = true
|
||||||
println(io, spc, "→ SSH remote: ", t.ssh ? "Yes" : "No")
|
defaultkw(::Val{:plugins}) = Plugin[]
|
||||||
println(io, spc, "→ Add packages to main environment: ", t.dev ? "Yes" : "No")
|
defaultkw(::Val{:disabled_defaults}) = DataType[]
|
||||||
println(io, spc, "→ Commit Manifest.toml: ", t.manifest ? "Yes" : "No")
|
function defaultkw(::Val{:authors})
|
||||||
|
name = LibGit2.getconfig("user.name", "")
|
||||||
print(io, spc, "→ Plugins:")
|
email = LibGit2.getconfig("user.email", "")
|
||||||
if isempty(t.plugins)
|
isempty(name) && return ""
|
||||||
print(io, " None")
|
author = name * " "
|
||||||
else
|
isempty(email) || (author *= "<$email>")
|
||||||
for plugin in sort(collect(values(t.plugins)); by=string)
|
return strip(author)
|
||||||
println(io)
|
|
||||||
buf = IOBuffer()
|
|
||||||
show(buf, plugin)
|
|
||||||
print(io, spc^2, "• ")
|
|
||||||
print(io, join(split(String(take!(buf)), "\n"), "\n$(spc^2)"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
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.license == "MIT"
|
||||||
@test t.authors == "foo"
|
@test t.authors == "foo"
|
||||||
@test t.dir == default_dir
|
@test t.dir == default_dir
|
||||||
@test t.julia_version == PkgTemplates.default_version()
|
@test t.julia_version == PkgTemplates.default_version
|
||||||
@test !t.ssh
|
@test !t.ssh
|
||||||
@test !t.manifest
|
@test !t.manifest
|
||||||
@test isempty(t.plugins)
|
@test isempty(t.plugins)
|
||||||
@ -107,7 +107,7 @@ end
|
|||||||
|
|
||||||
@testset "Show methods" begin
|
@testset "Show methods" begin
|
||||||
pkg_dir = replace(default_dir, homedir() => "~")
|
pkg_dir = replace(default_dir, homedir() => "~")
|
||||||
ver = PkgTemplates.version_floor(PkgTemplates.default_version())
|
ver = PkgTemplates.version_floor(PkgTemplates.default_version)
|
||||||
buf = IOBuffer()
|
buf = IOBuffer()
|
||||||
t = Template(; user=me, authors="foo")
|
t = Template(; user=me, authors="foo")
|
||||||
show(buf, t)
|
show(buf, t)
|
||||||
@ -327,12 +327,6 @@ end
|
|||||||
rm(temp_dir; recursive=true)
|
rm(temp_dir; recursive=true)
|
||||||
end
|
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
|
@testset "Git-less package generation" begin
|
||||||
t = Template(; user=me)
|
t = Template(; user=me)
|
||||||
generate(test_pkg, t; git=false)
|
generate(test_pkg, t; git=false)
|
||||||
@ -340,84 +334,6 @@ end
|
|||||||
@test !isfile(joinpath(t.dir, ".gitignore"))
|
@test !isfile(joinpath(t.dir, ".gitignore"))
|
||||||
end
|
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
|
@testset "Plugins" begin
|
||||||
t = Template(; user=me)
|
t = Template(; user=me)
|
||||||
pkg_dir = joinpath(t.dir, test_pkg)
|
pkg_dir = joinpath(t.dir, test_pkg)
|
||||||
@ -474,7 +390,8 @@ end
|
|||||||
warn_str = "Ignoring predefined Documenter kwargs \"format\" from additional kwargs"
|
warn_str = "Ignoring predefined Documenter kwargs \"format\" from additional kwargs"
|
||||||
check_kwargs(kwargs, warn_str)
|
check_kwargs(kwargs, warn_str)
|
||||||
|
|
||||||
kwargs = Dict(:checkdocs => :none,
|
kwargs = Dict(
|
||||||
|
:checkdocs => :none,
|
||||||
:strict => true,
|
:strict => true,
|
||||||
:format => :markdown,
|
:format => :markdown,
|
||||||
:stringarg => "string",
|
:stringarg => "string",
|
||||||
@ -488,5 +405,3 @@ end
|
|||||||
end
|
end
|
||||||
|
|
||||||
include(joinpath("interactive", "interactive.jl"))
|
include(joinpath("interactive", "interactive.jl"))
|
||||||
|
|
||||||
rm(test_file)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user