""" Git(; ignore=String[], ssh=false, manifest=false, gpgsign=false) Creates a Git repository and a `.gitignore` file. ## Keyword Arguments - `ignore::Vector{<:AbstractString}`: Patterns to add to the `.gitignore`. See also: [`gitignore`](@ref). - `manifest::Bool`: Whether or not to commit `Manifest.toml`. - `ssh::Bool`: Whether or not to use SSH for the remote. If left unset, HTTPS is used. - `gpgsign::Bool`: Whether or not to sign commits with your GPG key. This option requires that the Git CLI is installed. """ @with_kw_noshow struct Git <: Plugin ignore::Vector{String} = [] ssh::Bool = false manifest::Bool = false gpgsign::Bool = false end # Try to make sure that no files are created after we commit. priority(::Git, ::typeof(posthook)) = 5 Base.:(==)(a::Git, b::Git) = all(map(n -> getfield(a, n) == getfield(b, n), fieldnames(Git))) function gitignore(p::Git) ignore = copy(p.ignore) p.manifest || push!(ignore, "Manifest.toml") return ignore end # Set up the Git repository. function prehook(p::Git, t::Template, pkg_dir::AbstractString) if p.gpgsign && try run(pipeline(`git --version`; stdout=devnull)); false catch; true end throw(ArgumentError("Git: gpgsign is set but the Git CLI is not installed")) end LibGit2.with(LibGit2.init(pkg_dir)) do repo commit(p, repo, pkg_dir, "Initial commit") pkg = basename(pkg_dir) url = if p.ssh "git@$(t.host):$(t.user)/$pkg.jl.git" else "https://$(t.host)/$(t.user)/$pkg.jl" end LibGit2.with(GitRemote(repo, "origin", url)) do remote # TODO: `git pull` still requires some Git branch config. LibGit2.add_push!(repo, remote, "refs/heads/master") end end end # Create the .gitignore. function hook(p::Git, t::Template, pkg_dir::AbstractString) ignore = mapreduce(gitignore, append!, t.plugins) # Only ignore manifests at the repo root. p.manifest || "Manifest.toml" in ignore || push!(ignore, "/Manifest.toml") unique!(sort!(ignore)) gen_file(joinpath(pkg_dir, ".gitignore"), join(ignore, "\n")) end # Commit the files. function posthook(p::Git, ::Template, pkg_dir::AbstractString) # Ensure that the manifest exists if it's going to be committed. manifest = joinpath(pkg_dir, "Manifest.toml") if p.manifest && !isfile(manifest) touch(manifest) with_project(Pkg.update, pkg_dir) end LibGit2.with(GitRepo(pkg_dir)) do repo LibGit2.add!(repo, ".") msg = "Files generated by PkgTemplates" # TODO: Newer versions of Julia will not have Pkg.installed. installed = Pkg.installed() if haskey(installed, "PkgTemplates") ver = string(installed["PkgTemplates"]) msg *= "\n\nPkgTemplates version: $ver" end commit(p, repo, pkg_dir, msg) end end function commit(p::Git, repo::GitRepo, pkg_dir::AbstractString, msg::AbstractString) if p.gpgsign run(pipeline(`git -C $pkg_dir commit -S --allow-empty -m $msg`; stdout=devnull)) else LibGit2.commit(repo, msg) end end