Skip to content
Open
Show file tree
Hide file tree
Changes from all 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] - 2024-01-15

### 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