Skip to content
Draft
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
6 changes: 3 additions & 3 deletions sphinx/environment/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from sphinx.util.docutils import LoggingReporter
from sphinx.util.i18n import CatalogRepository, docname_to_domain
from sphinx.util.nodes import is_translatable
from sphinx.util.osutil import _last_modified_time, _relative_path
from sphinx.util.osutil import _last_modified_time, _relative_path, normalize_path

if TYPE_CHECKING:
from collections.abc import Callable, Iterable, Iterator, Mapping
Expand Down Expand Up @@ -438,7 +438,7 @@ def relfn2path(
"""
file_name = Path(filename)
if file_name.parts[:1] in {('/',), ('\\',)}:
abs_fn = self.srcdir.joinpath(*file_name.parts[1:]).resolve()
abs_fn = normalize_path(self.srcdir.joinpath(*file_name.parts[1:]))
else:
if not docname:
if self.docname:
Expand All @@ -447,7 +447,7 @@ def relfn2path(
msg = 'docname'
raise KeyError(msg)
doc_dir = self.doc2path(docname, base=False).parent
abs_fn = self.srcdir.joinpath(doc_dir, file_name).resolve()
abs_fn = normalize_path(self.srcdir.joinpath(doc_dir, file_name))

rel_fn = _relative_path(abs_fn, self.srcdir)
return rel_fn.as_posix(), os.fspath(abs_fn)
Expand Down
12 changes: 10 additions & 2 deletions sphinx/util/osutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ def path_stabilize(filepath: str | os.PathLike[str], /) -> str:
return unicodedata.normalize('NFC', new_path)


def normalize_path(filepath: Path, /) -> Path:
"""Normalize path by removing redundant separators and up-level references.
This *does not* resolve symbolic links.
"""
return filepath.__class__(os.path.normpath(filepath))


def relative_uri(base: str, to: str) -> str:
"""Return a relative URL from ``base`` to ``to``."""
if to.startswith(SEP):
Expand Down Expand Up @@ -179,9 +187,9 @@ def _relative_path(path: Path, root: Path, /) -> Path:
"""
# Path.relative_to() requires fully-resolved paths (no '..').
if '..' in path.parts:
path = path.resolve()
path = normalize_path(path)
if '..' in root.parts:
root = root.resolve()
root = normalize_path(root)

if path.anchor != root.anchor or '..' in root.parts:
# If the drives are different, no relative path exists.
Expand Down
Loading