Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set GIT_TEMPLATE_DIR when calling Git #1862

Merged
merged 10 commits into from
Jul 6, 2022
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

* ![Bugfix][badge-bugfix] When including docstrings for an alias, Documenter now correctly tries to include the exactly matching docstring first, before checking for signature subtypes. ([#1842][github-1842])
* ![Bugfix][badge-bugfix] When checking for missing docstrings, Documenter now correctly handles docstrings for methods that extend bindings from other modules that have not been imported into the current module. ([#1695][github-1695], [#1857][github-1857], [#1861][github-1861])
* ![Bugfix][badge-bugfix] By overriding `GIT_TEMPLATE_DIR`, `git` no longer picks up arbitrary user templates and hooks when internally called by Documenter. ([#1862][github-1862])

## Version `v0.27.19`

Expand Down Expand Up @@ -1083,6 +1084,7 @@
[github-1846]: https://github.com/JuliaDocs/Documenter.jl/pull/1846
[github-1857]: https://github.com/JuliaDocs/Documenter.jl/issues/1857
[github-1861]: https://github.com/JuliaDocs/Documenter.jl/pull/1861
[github-1862]: https://github.com/JuliaDocs/Documenter.jl/pull/1862
<!-- end of issue link definitions -->

[julia-38079]: https://github.com/JuliaLang/julia/issues/38079
Expand Down
36 changes: 18 additions & 18 deletions src/Documenter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ include("CrossReferences.jl")
include("DocChecks.jl")
include("Writers/Writers.jl")

import .Utilities: Selectors
import .Utilities: Selectors, git
import .Writers.HTMLWriter: HTML, asset
import .Writers.HTMLWriter.RD: KaTeX, MathJax, MathJax2, MathJax3
import .Writers.LaTeXWriter: LaTeX
Expand Down Expand Up @@ -564,7 +564,7 @@ function deploydocs(;
# the working directory has been changed (e.g. if the makedocs' build argument is
# outside root).
sha = try
readchomp(`git rev-parse --short HEAD`)
readchomp(`$(git()) rev-parse --short HEAD`)
catch
# git rev-parse will throw an error and return code 128 if it is not being
# run in a git repository, which will make run/readchomp throw an exception.
Expand Down Expand Up @@ -618,17 +618,17 @@ function git_push(
# Generate a closure with common commands for ssh and https
function git_commands(sshconfig=nothing)
# Setup git.
run(`git init`)
run(`git config user.name "Documenter.jl"`)
run(`git config user.email "documenter@juliadocs.github.io"`)
run(`$(git()) init`)
run(`$(git()) config user.name "Documenter.jl"`)
run(`$(git()) config user.email "documenter@juliadocs.github.io"`)
if sshconfig !== nothing
run(`git config core.sshCommand "ssh -F $(sshconfig)"`)
run(`$(git()) config core.sshCommand "ssh -F $(sshconfig)"`)
end

# Fetch from remote and checkout the branch.
run(`git remote add upstream $upstream`)
run(`$(git()) remote add upstream $upstream`)
try
run(`git fetch upstream`)
run(`$(git()) fetch upstream`)
catch e
@error """
Git failed to fetch $upstream
Expand All @@ -640,7 +640,7 @@ function git_push(
end

try
run(`git checkout -b $branch upstream/$branch`)
run(`$(git()) checkout -b $branch upstream/$branch`)
catch e
@info """
Checking out $branch failed, creating a new orphaned branch.
Expand All @@ -649,8 +649,8 @@ function git_push(
from Git in this situation.
"""
@debug "checking out $branch failed with error: $e"
run(`git checkout --orphan $branch`)
run(`git commit --allow-empty -m "Initial empty commit for docs"`)
run(`$(git()) checkout --orphan $branch`)
run(`$(git()) commit --allow-empty -m "Initial empty commit for docs"`)
end

# Copy docs to `subfolder` directory.
Expand Down Expand Up @@ -691,14 +691,14 @@ function git_push(
end

# Add, commit, and push the docs to the remote.
run(`git add -A .`)
if !success(`git diff --cached --exit-code`)
run(`$(git()) add -A .`)
if !success(`$(git()) diff --cached --exit-code`)
if forcepush
run(`git commit --amend --date=now -m "build based on $sha"`)
run(`git push -fq upstream HEAD:$branch`)
run(`$(git()) commit --amend --date=now -m "build based on $sha"`)
run(`$(git()) push -fq upstream HEAD:$branch`)
else
run(`git commit -m "build based on $sha"`)
run(`git push -q upstream HEAD:$branch`)
run(`$(git()) commit -m "build based on $sha"`)
run(`$(git()) push -q upstream HEAD:$branch`)
end
else
@debug "new docs identical to the old -- not committing nor pushing."
Expand Down Expand Up @@ -820,7 +820,7 @@ function gitrm_copy(src, dst)
if isdir(dst)
for x in filter!(!in((".git", "previews")), readdir(dst))
# --ignore-unmatch so that we wouldn't get errors if dst does not exist
run(`git rm -rf --ignore-unmatch $(joinpath(dst, x))`)
run(`$(git()) rm -rf --ignore-unmatch $(joinpath(dst, x))`)
end
end
# git rm also remove parent directories
Expand Down
28 changes: 20 additions & 8 deletions src/Utilities/Utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ end

function repo_commit(file)
cd(dirname(file)) do
readchomp(`git rev-parse HEAD`)
readchomp(`$(git()) rev-parse HEAD`)
end
end

Expand Down Expand Up @@ -515,7 +515,7 @@ const GIT_REMOTE_CACHE = Dict{String,String}()
function getremote(dir::AbstractString)
return get!(GIT_REMOTE_CACHE, dir) do
remote = try
readchomp(setenv(`git config --get remote.origin.url`; dir=dir))
readchomp(setenv(`$(git()) config --get remote.origin.url`; dir=dir))
catch
""
end
Expand All @@ -531,7 +531,7 @@ Returns the first 5 characters of the current git commit hash of the directory `
"""
function get_commit_short(dir)
commit = cd(dir) do
readchomp(`git rev-parse HEAD`)
readchomp(`$(git()) rev-parse HEAD`)
end
(length(commit) > 5) ? commit[1:5] : commit
end
Expand Down Expand Up @@ -790,13 +790,16 @@ it out automatically.
to construct the warning messages.
"""
function git_remote_head_branch(varname, root; remotename = "origin", fallback = "master")
env = copy(ENV)
env["GIT_TERMINAL_PROMPT"] = "0"
env["GIT_SSH_COMMAND"] = get(env, "GIT_SSH_COMMAND", "ssh -o \"BatchMode yes\"")
cmd = `git remote show $(remotename)`
# We need to do addenv() here to merge the new variables with the environment set by
# Git_jll and the git() function.
cmd = addenv(
setenv(`$(git()) remote show $(remotename)`, dir=root),
"GIT_TERMINAL_PROMPT" => "0",
"GIT_SSH_COMMAND" => get(ENV, "GIT_SSH_COMMAND", "ssh -o \"BatchMode yes\""),
)
stderr_output = IOBuffer()
git_remote_output = try
read(pipeline(setenv(cmd, env; dir=root); stderr = stderr_output), String)
read(pipeline(cmd; stderr = stderr_output), String)
catch e
@warn """
Unable to determine $(varname) from remote HEAD branch, defaulting to "$(fallback)".
Expand Down Expand Up @@ -846,6 +849,15 @@ dropheaders(h::Markdown.Header) = Markdown.Paragraph([Markdown.Bold(h.text)])
dropheaders(v::Vector) = map(dropheaders, v)
dropheaders(other) = other

function git(; kwargs...)
system_git_path = Sys.which("git")
isnothing(system_git_path) && error("Unable to find `git`")
# According to the Git man page, the default GIT_TEMPLATE_DIR is at /usr/share/git-core/templates
# We need to set this to something so that Git wouldn't pick up the user
# templates (e.g. from init.templateDir config).
return addenv(`$(system_git_path)`, "GIT_TEMPLATE_DIR" => "/usr/share/git-core/templates")
end

include("DOM.jl")
include("MDFlatten.jl")
include("TextDiff.jl")
Expand Down
18 changes: 11 additions & 7 deletions test/doctests/doctests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@ function run_makedocs(f, mdfiles, modules=Module[]; kwargs...)
touch(joinpath(srcdir, "index.md"))

c = IOCapture.capture(rethrow = InterruptException) do
makedocs(
sitename = " ",
format = Documenter.HTML(edit_link = "master"),
root = dir,
modules = modules;
kwargs...
)
# In case JULIA_DEBUG is set to something, we'll override that, so that we wouldn't
# get some unexpected debug output from makedocs.
withenv("JULIA_DEBUG" => "") do
makedocs(
sitename = " ",
format = Documenter.HTML(edit_link = "master"),
root = dir,
modules = modules;
kwargs...
)
end
end

@debug """run_makedocs($mdfiles, modules=$modules) -> $(c.error ? "fail" : "success")
Expand Down
58 changes: 31 additions & 27 deletions test/utilities.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
module UtilitiesTests

using Test
using Logging: Info
import Base64: stringmime
include("TestUtilities.jl"); using .TestUtilities

import Documenter
using Documenter.Utilities: git
import Markdown

module UnitTests
Expand Down Expand Up @@ -166,15 +168,15 @@ end
mkpath(path_repo)
cd(path_repo) do
# Create a simple mock repo in a temporary directory with a single file.
@test trun(`git init`)
@test trun(`git config user.email "tester@example.com"`)
@test trun(`git config user.name "Test Committer"`)
@test trun(`git remote add origin git@github.com:JuliaDocs/Documenter.jl.git`)
@test trun(`$(git()) init`)
@test trun(`$(git()) config user.email "tester@example.com"`)
@test trun(`$(git()) config user.name "Test Committer"`)
@test trun(`$(git()) remote add origin git@github.com:JuliaDocs/Documenter.jl.git`)
mkpath("src")
filepath = abspath(joinpath("src", "SourceFile.jl"))
write(filepath, "X")
@test trun(`git add -A`)
@test trun(`git commit -m"Initial commit."`)
@test trun(`$(git()) add -A`)
@test trun(`$(git()) commit -m"Initial commit."`)

# Run tests
commit = Documenter.Utilities.repo_commit(filepath)
Expand All @@ -194,7 +196,7 @@ end
# Test worktree
path_worktree = joinpath(path, "worktree")
cd("$(path_repo)") do
@test trun(`git worktree add $(path_worktree)`)
@test trun(`$(git()) worktree add $(path_worktree)`)
end
cd("$(path_worktree)") do
filepath = abspath(joinpath("src", "SourceFile.jl"))
Expand All @@ -217,15 +219,15 @@ end
path_submodule = joinpath(path, "submodule")
mkpath(path_submodule)
cd(path_submodule) do
@test trun(`git init`)
@test trun(`git config user.email "tester@example.com"`)
@test trun(`git config user.name "Test Committer"`)
@test trun(`$(git()) init`)
@test trun(`$(git()) config user.email "tester@example.com"`)
@test trun(`$(git()) config user.name "Test Committer"`)
# NOTE: the target path in the `git submodule add` command is necessary for
# Windows builds, since otherwise Git claims that the path is in a .gitignore
# file.
@test trun(`git submodule add $(path_repo) repository`)
@test trun(`git add -A`)
@test trun(`git commit -m"Initial commit."`)
@test trun(`$(git()) submodule add $(path_repo) repository`)
@test trun(`$(git()) add -A`)
@test trun(`$(git()) commit -m"Initial commit."`)
end
path_submodule_repo = joinpath(path, "submodule", "repository")
@test isdir(path_submodule_repo)
Expand Down Expand Up @@ -540,7 +542,7 @@ end

function git_create_bare_repo(path; head = nothing)
mkdir(path)
@test trun(`git -C $(path) init --bare`)
@test trun(`$(git()) -C $(path) init --bare`)
@test isfile(joinpath(path, "HEAD"))
if head !== nothing
write(joinpath(path, "HEAD"), """
Expand All @@ -551,34 +553,36 @@ end
# We need to commit something to the non-standard branch to actually
# "activate" the non-standard HEAD:
head = (head === nothing) ? "master" : head
@test trun(`git clone $(path) $(subdir_path)`)
@test trun(`git -C $(subdir_path) config user.email "tester@example.com"`)
@test trun(`git -C $(subdir_path) config user.name "Test Committer"`)
@test trun(`git -C $(subdir_path) checkout -b $(head)`)
@test trun(`git -C $(subdir_path) commit --allow-empty -m"initial empty commit"`)
@test trun(`git -C $(subdir_path) push --set-upstream origin $(head)`)
@test trun(`$(git()) clone $(path) $(subdir_path)`)
@test trun(`$(git()) -C $(subdir_path) config user.email "tester@example.com"`)
@test trun(`$(git()) -C $(subdir_path) config user.name "Test Committer"`)
@test trun(`$(git()) -C $(subdir_path) checkout -b $(head)`)
@test trun(`$(git()) -C $(subdir_path) commit --allow-empty -m"initial empty commit"`)
@test trun(`$(git()) -C $(subdir_path) push --set-upstream origin $(head)`)
end
end

mktempdir() do path
cd(path) do
# Note: running @test_logs with match_mode=:any here so that the tests would
# also pass when e.g. JULIA_DEBUG=Documenter when the tests are being run.
# If there is no parent remote repository, we should get a warning and the fallback value:
@test (@test_logs (:warn,) Documenter.Utilities.git_remote_head_branch(".", pwd(); fallback = "fallback")) == "fallback"
@test (@test_logs (:warn,) Documenter.Utilities.git_remote_head_branch(".", pwd())) == "master"
@test (@test_logs (:warn,) match_mode=:any Documenter.Utilities.git_remote_head_branch(".", pwd(); fallback = "fallback")) == "fallback"
@test (@test_logs (:warn,) match_mode=:any Documenter.Utilities.git_remote_head_branch(".", pwd())) == "master"
# We'll set up two "remote" bare repositories with non-standard HEADs:
git_create_bare_repo("barerepo", head = "maindevbranch")
git_create_bare_repo("barerepo_other", head = "main")
# Clone barerepo and test git_remote_head_branch:
@test trun(`git clone barerepo/ local/`)
@test trun(`$(git()) clone barerepo/ local/`)
@test Documenter.Utilities.git_remote_head_branch(".", "local") == "maindevbranch"
# Now, let's add the other repo as another remote, and fetch the HEAD for that:
@test trun(`git -C local/ remote add other ../barerepo_other/`)
@test trun(`git -C local/ fetch other`)
@test trun(`$(git()) -C local/ remote add other ../barerepo_other/`)
@test trun(`$(git()) -C local/ fetch other`)
@test Documenter.Utilities.git_remote_head_branch(".", "local") == "maindevbranch"
@test Documenter.Utilities.git_remote_head_branch(".", "local"; remotename = "other") == "main"
# Asking for a nonsense remote should also warn and drop back to fallback:
@test (@test_logs (:warn,) Documenter.Utilities.git_remote_head_branch(".", pwd(); remotename = "nonsense", fallback = "fallback")) == "fallback"
@test (@test_logs (:warn,) Documenter.Utilities.git_remote_head_branch(".", pwd(); remotename = "nonsense")) == "master"
@test (@test_logs (:warn,) match_mode=:any Documenter.Utilities.git_remote_head_branch(".", pwd(); remotename = "nonsense", fallback = "fallback")) == "fallback"
@test (@test_logs (:warn,) match_mode=:any Documenter.Utilities.git_remote_head_branch(".", pwd(); remotename = "nonsense")) == "master"
end
end
end
Expand Down