diff --git a/CHANGELOG.md b/CHANGELOG.md index 86442f4..bcd4073 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Fixed +- Automatic head branch detection (introduced in version 2.11.0) caused a performance + regression since the `git remote show` command takes ~1 second. For documentation builds + with many literate files this caused significant slowdowns, which is particularly annoying + when doing iterative buils with eg. + [LiveServer.jl](https://github.com/tlienart/LiveServer.jl). Literate now caches the remote + head branch on a per-repo basis, so the 1 second delay should only be noticed on the first + run of the first file in a repo. As noted in the changelog entry for 2.11.0 it is also + possible to specify the head branch by passing the `edit_commit` keyword argument. Doing + so will now completely skip the slow `git` command. ([#198][github-198]) ## [2.13.3] - 2022-05-21 ### Fixed @@ -14,7 +24,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 `GIT_SSH_COMMAND='ssh -o "BatchMode yes"'` to supress prompts when using ssh. ([#197][github-197]) - ## [2.13.2] - 2022-04-22 ### Fixed - Set current working directory for markdown execution to the output directory, just like @@ -218,6 +227,7 @@ https://discourse.julialang.org/t/ann-literate-jl/10651 for release announcement [github-194]: https://github.com/fredrikekre/Literate.jl/pull/194 [github-195]: https://github.com/fredrikekre/Literate.jl/pull/195 [github-197]: https://github.com/fredrikekre/Literate.jl/issues/197 +[github-198]: https://github.com/fredrikekre/Literate.jl/pull/198 [Unreleased]: https://github.com/fredrikekre/Literate.jl/compare/v2.13.3...HEAD [2.13.3]: https://github.com/fredrikekre/Literate.jl/compare/v2.13.2...v2.13.3 diff --git a/src/Literate.jl b/src/Literate.jl index 962c975..a6053a7 100644 --- a/src/Literate.jl +++ b/src/Literate.jl @@ -228,6 +228,58 @@ isdocumenter(cfg) = cfg["flavor"]::AbstractFlavor isa DocumenterFlavor _DEFAULT_IMAGE_FORMATS = [(MIME("image/svg+xml"), ".svg"), (MIME("image/png"), ".png"), (MIME("image/jpeg"), ".jpeg")] +# Cache of inputfile => head branch +const HEAD_BRANCH_CACHE = Dict{String,String}() + +# Guess the package (or repository) root url with "master" as fallback +# see JuliaDocs/Documenter.jl#1751 +function edit_commit(inputfile, user_config) + fallback_edit_commit = "master" + if (c = get(user_config, "edit_commit", nothing); c !== nothing) + return c + end + if (git = Sys.which("git"); git !== nothing) + # Check the cache for the git root + git_root = try + readchomp( + pipeline( + setenv(`$(git) rev-parse --show-toplevel`; dir=dirname(inputfile)); + stderr=devnull, + ) + ) + catch + end + if (c = get(HEAD_BRANCH_CACHE, git_root, nothing); c !== nothing) + return c + end + # Check the cache for the file + if (c = get(HEAD_BRANCH_CACHE, inputfile, nothing); c !== nothing) + return c + end + # Fallback to git remote show + env = copy(ENV) + # Set environment variables to block interactive prompt + env["GIT_TERMINAL_PROMPT"] = "0" + env["GIT_SSH_COMMAND"] = get(ENV, "GIT_SSH_COMMAND", "ssh -o \"BatchMode yes\"") + str = try + read( + pipeline( + setenv(`$(git) remote show origin`, env; dir=dirname(inputfile)), + stderr=devnull, + ), + String, + ) + catch + end + if str !== nothing && (m = match(r"^\s*HEAD branch:\s*(.*)$"m, str); m !== nothing) + head = String(m[1]) + HEAD_BRANCH_CACHE[something(git_root, inputfile)] = head + return head + end + end + return fallback_edit_commit +end + function create_configuration(inputfile; user_config, user_kwargs, type=nothing) # Combine user config with user kwargs user_config = Dict{String,Any}(string(k) => v for (k, v) in user_config) @@ -265,25 +317,7 @@ function create_configuration(inputfile; user_config, user_kwargs, type=nothing) ("````@example $(get(user_config, "name", replace(cfg["name"], r"\s" => "_")))" => "````") : ("````julia" => "````") cfg["image_formats"] = _DEFAULT_IMAGE_FORMATS - # Guess the package (or repository) root url with "master" as fallback - # see JuliaDocs/Documenter.jl#1751 - fallback_edit_commit = "master" - if (git = Sys.which("git"); git !== nothing) - try - env = copy(ENV) - # Set environment variables to block interactive prompt - env["GIT_TERMINAL_PROMPT"] = "0" - env["GIT_SSH_COMMAND"] = get(ENV, "GIT_SSH_COMMAND", "ssh -o \"BatchMode yes\"") - str = read(pipeline(ignorestatus( - setenv(`$(git) remote show origin`, env; dir=dirname(inputfile)) - ), stderr=devnull), String) - if (m = match(r"^\s*HEAD branch:\s*(.*)$"m, str); m !== nothing) - fallback_edit_commit = String(m[1]) - end - catch - end - end - cfg["edit_commit"] = get(user_config, "edit_commit", fallback_edit_commit) + cfg["edit_commit"] = edit_commit(inputfile, user_config) deploy_branch = "gh-pages" # TODO: Make this configurable like Documenter? # Strip build version from a tag (cf. JuliaDocs/Documenter.jl#1298, Literate.jl#162) function version_tag_strip_build(tag)