Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
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).

## Version [v1.2.2] - 2023-12-10

### Fixed

* Fix the handling of file paths in source URL generation, to fix standard library links in the Julia manual. ([#2372])

## Version [v1.2.1] - 2023-12-02

### Fixed
Expand Down Expand Up @@ -1297,6 +1303,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[v1.1.2]: https://github.com/JuliaDocs/Documenter.jl/releases/tag/v1.1.2
[v1.2.0]: https://github.com/JuliaDocs/Documenter.jl/releases/tag/v1.2.0
[v1.2.1]: https://github.com/JuliaDocs/Documenter.jl/releases/tag/v1.2.1
[v1.2.2]: https://github.com/JuliaDocs/Documenter.jl/releases/tag/v1.2.2
[#198]: https://github.com/JuliaDocs/Documenter.jl/issues/198
[#245]: https://github.com/JuliaDocs/Documenter.jl/issues/245
[#487]: https://github.com/JuliaDocs/Documenter.jl/issues/487
Expand Down Expand Up @@ -1765,6 +1772,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#2348]: https://github.com/JuliaDocs/Documenter.jl/issues/2348
[#2364]: https://github.com/JuliaDocs/Documenter.jl/issues/2364
[#2365]: https://github.com/JuliaDocs/Documenter.jl/issues/2365
[#2372]: https://github.com/JuliaDocs/Documenter.jl/issues/2372
[JuliaLang/julia#36953]: https://github.com/JuliaLang/julia/issues/36953
[JuliaLang/julia#38054]: https://github.com/JuliaLang/julia/issues/38054
[JuliaLang/julia#39841]: https://github.com/JuliaLang/julia/issues/39841
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "Documenter"
uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
version = "1.2.1"
version = "1.2.2"

[deps]
ANSIColoredPrinters = "a4c015fc-c6ff-483c-b24f-f7ea428134e9"
Expand Down
43 changes: 37 additions & 6 deletions src/documents.jl
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ struct RemoteRepository
end
function RemoteRepository(root::AbstractString, remote::Remotes.Remote)
try
RemoteRepository(realpath(root), remote, repo_commit(root))
RemoteRepository(normpath(root), remote, repo_commit(root))
catch e
e isa RepoCommitError || rethrow()
@error "Unable to determine the commit for the remote repository:\n$(e.msg)" e.directory exception = e.err_bt
Expand Down Expand Up @@ -507,7 +507,7 @@ function interpret_repo_and_remotes(; root, repo, remotes)
if !isdir(path)
throw(ArgumentError(("Invalid local path in remotes (not a directory): $(path)")))
end
path = realpath(path)
path = normpath(path)
# We'll also check that there are no duplicate entries.
idx = findfirst(isequal(path), [remote.root for remote in remotes_checked])
if !isnothing(idx)
Expand Down Expand Up @@ -788,9 +788,30 @@ function relpath_from_remote_root(doc::Document, path::AbstractString)
end
ispath(path) || error("relpath_from_repo_root called with nonexistent path: $path")
isabspath(path) || error("relpath_from_repo_root called with non-absolute path: $path")
# We want to expand the path properly, including symlinks, so we call realpath()
# Note: it throws for non-existing files, but we just checked for it.
path = realpath(path)
# We'll normalize the path, removing `..`-s etc.
#
# However, we explicitly do not want to resolve symlinks (so we can't call `realpath`).
# This is, in particular, necessary to enable us to resolve standard library paths for
# the Julia manual -- the standard library source files under usr/share/julia are _sometimes_
# symlinked to stdlib/ and sometimes they are not.
#
# Specifically, the (fixed; i.e. `Base.fixup_stdlib_path` has been called) paths of standard
# library docstrings always point into
#
# $(JULIA_SOURCE)/usr/share/julia/stdlib/v1.11/$(PACKAGE)/src/...
#
# If this is a Julia worktree that has been created by unpacking a pre-built tarball (like we
# do in the Julia documentation builds on CI), then those are real files. However, if you are
# building the documentation in a full local Julia worktree, then the standard library package
# directories are actually symlinks into $(JULIA_SOURCE)/stdlib. This would throw `realpath`
# off.
#
# For the normal case of building documentation for Julia packages, we do not expect to have to
# deal with symlinks at all, unless it's a very strange setup. However, even in that case, it
# feels safer to _not_ expand symlinks, since the symlinks might be used to organize directories
# at a higher level (e.g. closer to the root; link symlinking /home directories or something
# strange like that).
path = normpath(path)
# Try to see if `path` falls into any of the remotes in .remotes, or if it's a GitHub repository
# we can automatically "configure".
root_remote::Union{RemoteRepository,Nothing} = nothing
Expand Down Expand Up @@ -889,7 +910,17 @@ function source_url(doc::Document, mod::Module, file::AbstractString, linerange)
return repofile(julia_remote, ref, "base/$file", linerange)
end
# Generally, we assume that the Julia source file exists on the system.
isfile(file) || return nothing
# An exception to this is when the path points to a docstring in a standard library.
# To handle that case, we first "fix up" the path, hopefully making it point to the
# local usr/share/julia directory.
if !isfile(file)
# Note: Base.fixup_stdlib_path is a non-public internal function.
file = Base.fixup_stdlib_path(file)
end
if !isfile(file)
@warn "Trying to generate a source URL for a non-existent file" mod file linerange
return nothing
end
remoteref = relpath_from_remote_root(doc, file)
if isnothing(remoteref)
throw(MissingRemoteError(; path = file, linerange, mod))
Expand Down
6 changes: 1 addition & 5 deletions src/utilities/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -390,14 +390,10 @@ If `path` is a directory, it may itself already be a root.
The predicate `f` gets called with absolute paths to directories and must return `true`
if the directory is a "root". An example predicate is `is_git_repo_root` that checks if
the directory is a Git repository root.

The `dbdir` keyword argument specifies the name of the directory we are searching for to
determine if this is a repository or not. If there is a file called `dbdir`, then it's
contents is checked under the assumption that it is a Git worktree or a submodule.
"""
function find_root_parent(f, path)
ispath(path) || throw(ArgumentError("find_root_parent called with non-existent path\n path: $path"))
path = realpath(path)
path = normpath(path)
parent_dir = isdir(path) ? path : dirname(path)
parent_dir_last = ""
while parent_dir != parent_dir_last
Expand Down
17 changes: 17 additions & 0 deletions test/base_assumptions.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""
These tests test assumptions about the Julia Base module. In particular, this will
test the presence of the various internal, non-public functions that are used by
Documenter.jl.
"""
module BaseAssumptionTests
using Test

@testset "Julia Base assumptions" begin
# To handle source URLs to standard library files, we need to fix up the paths to
# standard library objects (which generally point to /cache/..., for the pre-built
# binaries).
@test isdefined(Base, :fixup_stdlib_path)
@test hasmethod(Base.fixup_stdlib_path, (String,))
end

end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ end
@quietly include("plugins/make.jl")

# Unit tests for module internals.
include("base_assumptions.jl")
include("except.jl")
include("utilities.jl")

Expand Down
6 changes: 3 additions & 3 deletions test/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ end
@test Documenter.source_url(doc, Documenter, filepath, 10:20) == "//blob/$(commit)/src/SourceFile.jl#L10-L20"

# repo_root & relpath_from_repo_root
@test repo_root(filepath) == realpath(joinpath(dirname(filepath), ".."))
@test repo_root(filepath) == rstrip(normpath(joinpath(dirname(filepath), "..")), ['\\', '/']) # normpath() leaves a trailing /
@test repo_root(filepath, ".svn") === nothing
let remoteref = Documenter.relpath_from_remote_root(doc, filepath)
@test remoteref.repo.remote === remote
Expand All @@ -235,7 +235,7 @@ end
@test Documenter.source_url(doc, Documenter, filepath, 10:20) == "//blob/$(commit)/src/SourceFile.jl#L10-L20"

# repo_root & relpath_from_repo_root
@test repo_root(filepath) == realpath(joinpath(dirname(filepath), ".."))
@test repo_root(filepath) == rstrip(normpath(joinpath(dirname(filepath), "..")), ['\\', '/']) # normpath() leaves a trailing /
@test repo_root(filepath, ".svn") === nothing
let remoteref = Documenter.relpath_from_remote_root(doc, filepath)
@test remoteref.repo.remote === remote
Expand Down Expand Up @@ -278,7 +278,7 @@ end
@test Documenter.source_url(doc, Documenter, filepath, 10:20) == "//blob/$(commit)/src/SourceFile.jl#L10-L20"

# repo_root & relpath_from_repo_root
@test repo_root(filepath) == realpath(joinpath(dirname(filepath), ".."))
@test repo_root(filepath) == rstrip(normpath(joinpath(dirname(filepath), "..")), ['\\', '/']) # normpath() leaves a trailing /
@test repo_root(filepath, ".svn") === nothing
let remoteref = Documenter.relpath_from_remote_root(doc, filepath)
@test remoteref.repo.remote === remote
Expand Down