././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4471574 sphinxext_rediraffe-0.3.0/LICENCE.rst0000644000000000000000000000211515066252326014303 0ustar00Copyright (c) 2020, Vasista Vovveti Copyright (c) 2025, the Sphinx developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4471574 sphinxext_rediraffe-0.3.0/README.rst0000644000000000000000000000252715066252326014205 0ustar00=================== sphinxext-rediraffe =================== .. image:: https://img.shields.io/pypi/v/sphinxext-rediraffe.svg :target: https://pypi.org/project/sphinxext-rediraffe/ :alt: Package on PyPI .. image:: https://github.com/sphinx-doc/sphinxext-rediraffe/actions/workflows/test.yml/badge.svg :target: https://github.com/sphinx-doc/sphinxext-rediraffe/actions :alt: Build Status .. image:: https://img.shields.io/badge/License-MIT-blue.svg :target: https://opensource.org/licenses/MIT :alt: MIT Sphinx extension to redirect files .. image:: ./assets/rediraffe_logo.svg :align: center This Sphinx extension redirects non-existent pages to working pages. Rediraffe can also check that deleted or renamed files in your git repo are redirected. Rediraffe creates a graph of all specified redirects and traverses it to point all internal urls to leaf urls. This means that chained redirects will be resolved. For example, if a config has 6 chained redirects, all 6 links will redirect directly to the final link. The end user will never experience more than 1 redirection. Note: Rediraffe supports the html and dirhtml builders. Installation ============ .. code-block:: sh python -m pip install sphinxext-rediraffe Usage ===== See the `documentation`_. .. _documentation: https://sphinxext-rediraffe.readthedocs.io/en/latest/ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4531574 sphinxext_rediraffe-0.3.0/docs/Makefile0000644000000000000000000000117215066252326015101 0ustar00# Minimal makefile for Sphinx documentation # # You can set these variables from the command line, and also # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4531574 sphinxext_rediraffe-0.3.0/docs/conf.py0000644000000000000000000000113315066252326014735 0ustar00from __future__ import annotations import sphinxext.rediraffe copyright = ( '2020, FIRST', '2025-%Y, the Sphinx developers', ) version = release = sphinxext.rediraffe.__version__ master_doc = 'index' project = 'sphinxext-rediraffe' exclude_patterns = ['_build'] nitpicky = True html_theme = 'furo' html_logo = '../assets/rediraffe_logo_128.png' extensions = [ 'sphinx.ext.intersphinx', 'sphinxext.rediraffe', ] intersphinx_mapping = { 'sphinx': ('https://www.sphinx-doc.org/', None), } rediraffe_redirects = { 'other.rst': 'index.rst', 'other2.rst': 'other.rst', } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4531574 sphinxext_rediraffe-0.3.0/docs/index.rst0000644000000000000000000001154015066252326015302 0ustar00=================== sphinxext-rediraffe =================== .. role:: code-py(code) :language: Python This Sphinx extension redirects non-existent pages to working pages. Rediraffe can also check that deleted or renamed files in your git repo are redirected. Rediraffe creates a graph of all specified redirects and traverses it to point all internal urls to leaf urls. This means that chained redirects will be resolved. For example, if a config has 6 chained redirects, all 6 links will redirect directly to the final link. The end user will never experience more than 1 redirection. Note: Rediraffe supports the html and dirhtml builders. Installation ============ .. code-block:: sh python -m pip install sphinxext-rediraffe Usage ===== Just add ``sphinxext.rediraffe`` to the extensions list in :file:`conf.py`, .. code-block:: python extensions = [ 'sphinxext.rediraffe', ] and set :confval:`rediraffe_redirects` to a dict or file of redirects. Diff Checker ------------ The diff checker ensures that deleted or renamed files in your git repo are in your redirects. To run the diff checker: 1. Set :confval:`rediraffe_branch` and :confval:`rediraffe_redirects` in :file:`conf.py`. 2. Run the ``rediraffecheckdiff`` builder. Auto Redirect builder --------------------- The auto redirect builder can be used to automatically add renamed files to your redirects file. Simply run the ``rediraffewritediff`` builder. To run the auto redirecter: 1. Set :confval:`rediraffe_branch` and :confval:`rediraffe_redirects` in :file:`conf.py`. 2. Run the ``rediraffewritediff`` builder. Note: The auto redirect builder only works with a configuration file. Note: Deleted files cannot be added to your redirects file automatically. Options ======= These values are placed in the :file:`conf.py` of your Sphinx project. .. confval:: rediraffe_branch :type: :code-py:`str` :default: :code-py:`''` **Required** for the ``rediraffecheckdiff`` & ``rediraffewritediff`` builders. The branch or commit to diff against. .. confval:: rediraffe_redirects :type: :code-py:`str | dict[str, str]` A filename or dict containing redirects. .. confval:: rediraffe_template :type: :code-py:`str` :default: :code-py:`None` A jinja template to use to render the inserted redirecting files. If not specified, a default template will be used. This template will only be accessed after the html/htmldir builder is finished, meaning that this file may be generated as part of your build. Variables available to :confval:`!rediraffe_template`: ``from_file`` the file being redirected as written in :confval:`rediraffe_redirects`. ``to_file`` the destination file that from_file is redirected to as written in :confval:`rediraffe_redirects`. ``from_url`` the path to ``from_url``'s html file (built by rediraffe) relative to the :confval:`!outdir`. ``to_url`` the path to ``to_url``'s built html file relative to the :confval:`!outdir`. ``rel_url`` the relative path from ``from_url`` to ``to_url``. .. confval:: rediraffe_auto_redirect_perc :type: :code-py:`int` :default: :code-py:`100` Only used by the ``rediraffewritediff`` builder. The percentage as an integer representing the accuracy required before auto redirecting with the ``rediraffewritediff`` builder. Example Config ============== redirects only (file) --------------------- :file:`conf.py`: .. code-block:: python rediraffe_redirects = 'redirects.txt' :file:`redirects.txt`: .. code-block:: text # comments start with '#' 'another file.rst' index.rst another2.rst "another file.rst" Note: Filepaths can be wrapped in quotes (single or double). This is especially useful for filepaths containing spaces. redirects only (dict) --------------------- :file:`conf.py`: .. code-block:: python rediraffe_redirects = { 'another.rst': 'index.rst', 'another2.rst': 'another.rst', } redirects + diff checker ------------------------ :file:`conf.py`: .. code-block:: python rediraffe_redirects = 'redirects.txt' rediraffe_branch = 'main~1' redirects with jinja template ----------------------------- :file:`conf.py`: .. code-block:: python rediraffe_redirects = 'redirects.txt' rediraffe_template = 'template.html' :file:`template.html`: .. code-block:: html

Your destination is {{to_url}}

A complex example can be found at :file:`tests/roots/ext/`. Testing ======= Rediraffe uses pytest for testing. To run tests: 1. Install this package 2. Install test dependencies .. code-block:: sh python -m pip install --group test 3. Navigate to the tests directory and run .. code-block:: sh python -m pytest --headless The ``--headless`` flag ensures that a browser window does not open during browser backed selenium testing. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4531574 sphinxext_rediraffe-0.3.0/docs/make.bat0000644000000000000000000000143315066252326015046 0ustar00@ECHO OFF pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=. set BUILDDIR=_build if "%1" == "" goto help %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% goto end :help %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% :end popd ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4531574 sphinxext_rediraffe-0.3.0/pyproject.toml0000644000000000000000000000411615066252326015426 0ustar00[build-system] requires = ["flit_core>=3.12"] build-backend = "flit_core.buildapi" # project metadata [project] name = "sphinxext-rediraffe" description = "Sphinx Extension that redirects non-existent pages to working pages" readme = "README.rst" urls.Code = "https://github.com/sphinx-doc/sphinxext-rediraffe/" urls.Documentation = "https://sphinxext-rediraffe.readthedocs.io/" urls.Download = "https://pypi.org/project/sphinxext-rediraffe/" urls.Homepage = "https://github.com/sphinx-doc/sphinxext-rediraffe/" urls."Issue tracker" = "https://github.com/sphinx-doc/sphinxext-rediraffe/issues" license = "MIT" license-files = [ "LICENCE.rst", ] requires-python = ">=3.9" # Classifiers list: https://pypi.org/classifiers/ classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Environment :: Web Environment", "Framework :: Sphinx :: Extension", "Intended Audience :: Developers", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python", "Topic :: Documentation :: Sphinx", "Topic :: Documentation", "Topic :: Software Development :: Documentation", "Topic :: Text Processing", "Topic :: Utilities", ] dependencies = [ "Sphinx>=6.0", ] dynamic = ["version"] [[project.authors]] name = "Vasista Vovveti" email = "vasistavovveti@gmail.com" [dependency-groups] docs = [ "furo>=2024", "sphinx~=8.2.0", ] lint = [ "ruff==0.13.2", ] package = [ "betterproto==2.0.0b6", # resolution fails without betterproto "build", "pypi-attestations==0.0.27", "twine>=6.1", ] test = [ "pytest", "seleniumbase", ] [tool.flit.module] name = "sphinxext.rediraffe" [tool.flit.sdist] include = [ # Documentation "docs/", # Tests "tests/", "tox.ini", ] exclude = [ "docs/_build", ] [tool.uv] default-groups = "all" ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4531574 sphinxext_rediraffe-0.3.0/sphinxext/rediraffe.py0000644000000000000000000004072615066252326017054 0ustar00from __future__ import annotations import json import re import subprocess from os.path import relpath from pathlib import Path, PurePosixPath, PureWindowsPath from jinja2 import Environment, FileSystemLoader, Template from sphinx.builders import Builder from sphinx.builders.dirhtml import DirectoryHTMLBuilder from sphinx.builders.html import StandaloneHTMLBuilder from sphinx.builders.linkcheck import CheckExternalLinksBuilder from sphinx.errors import ExtensionError from sphinx.util import logging from sphinx.util.console import green, red, yellow # pylint: disable=no-name-in-module TYPE_CHECKING = False if TYPE_CHECKING: from sphinx.application import Sphinx from sphinx.util.typing import ExtensionMetadata __version__ = '0.3.0' version_info = (0, 3, 0) logger = logging.getLogger(__name__) DEFAULT_REDIRAFFE_TEMPLATE = Template( """

You should have been redirected.

If not, click here to continue. """ ) REDIRECT_JSON_NAME = '_rediraffe_redirected.json' RE_OBJ = re.compile(r"(?:(\"|')(.*?)\1|(\S+))\s+(?:(\"|')(.*?)\4|(\S+))") READTHEDOCS_BUILDERS = ['readthedocs', 'readthedocsdirhtml'] def create_graph(path: Path) -> dict[str, str]: """ Convert a file containing a whitespace delimited edge list (key value pairs) to a dict. Throws error on duplicate keys. """ graph_edges = {} broken = False with path.open(encoding='utf-8') as file: lines = file.readlines() for line_num, line in enumerate(lines, start=1): line = line.strip() if len(line) == 0 or line.startswith('#'): continue match = RE_OBJ.fullmatch(line) if match is None: logger.error( red(f'rediraffe: line {line_num} of the redirects is invalid!') ) broken = True continue edge_from = match.group(2) or match.group(3) edge_to = match.group(5) or match.group(6) if edge_from in graph_edges: # Duplicate vertices not allowed / Vertices can only have 1 outgoing edge logger.error( red( f'rediraffe: {edge_from} is redirected multiple times in the rediraffe_redirects file!' ) ) broken = True graph_edges[edge_from] = edge_to if broken: err_msg = 'rediraffe: Error(s) in parsing the redirects file.' logger.error(err_msg) raise ExtensionError(err_msg) return graph_edges def create_simple_redirects(graph_edges: dict) -> dict: """ Ensures that a graph is a acyclic and reconnects every vertex to its leaf vertex. """ redirects = {} broken_vertices = set() for vertex in graph_edges: if vertex in broken_vertices: continue visited = [] while vertex in graph_edges: if vertex in visited: # Ensure graph is a DAG logger.error( red( 'rediraffe: A circular redirect exists. Links involved: ' + ' -> '.join(visited + [vertex]) ) ) broken_vertices.update(visited) break visited.append(vertex) vertex = graph_edges[vertex] # vertex is now a leaf for visited_vertex in visited: redirects[visited_vertex] = vertex if broken_vertices: err_msg = ( 'rediraffe: At least 1 circular redirect detected. All involved links: ' + ', '.join(broken_vertices) ) logger.error(err_msg) raise ExtensionError(err_msg) return redirects def remove_suffix(docname: str, suffixes: list[str]) -> str: """Remove any known suffixes for a file path.""" for suffix in suffixes: if docname.endswith(suffix): return docname[: -len(suffix)] return docname def build_redirects(app: Sphinx, exception: Exception | None) -> None: """ Build amd write redirects """ redirect_json_file = Path(app.outdir) / REDIRECT_JSON_NAME if redirect_json_file.exists(): redirect_record = json.loads(redirect_json_file.read_bytes()) else: redirect_record = {} if exception is not None: return if isinstance(app.builder, CheckExternalLinksBuilder): logger.info('rediraffe: Redirect generation skipped for linkcheck builders.') return if ( type(app.builder) not in (StandaloneHTMLBuilder, DirectoryHTMLBuilder) and app.builder.name not in READTHEDOCS_BUILDERS ): logger.info( 'rediraffe: Redirect generation skipped for unsupported builders. Supported builders: html, dirhtml, readthedocs, readthedocsdirhtml.' ) return rediraffe_template = app.config.rediraffe_template if isinstance(rediraffe_template, str): # path template_path = Path(app.srcdir) / rediraffe_template if template_path.exists(): file_loader = FileSystemLoader(template_path.parent) env = Environment(loader=file_loader) rediraffe_template = env.get_template(template_path.name) else: logger.warning( 'rediraffe: rediraffe_template does not exist. The default will be used.' ) rediraffe_template = DEFAULT_REDIRAFFE_TEMPLATE else: rediraffe_template = DEFAULT_REDIRAFFE_TEMPLATE graph_edges = {} rediraffe_redirects = app.config.rediraffe_redirects if isinstance(rediraffe_redirects, dict): # dict in conf.py graph_edges = rediraffe_redirects elif isinstance(rediraffe_redirects, str): # filename path = Path(app.srcdir) / rediraffe_redirects if not path.is_file(): logger.error( red( 'rediraffe: rediraffe_redirects file does not exist. Redirects will not be generated.' ) ) app.statuscode = 1 return try: graph_edges = create_graph(path) except ExtensionError as e: app.statuscode = 1 raise e else: logger.warning( 'rediraffe: rediraffe was not given redirects to process. Redirects will not be generated.' ) return try: redirects = create_simple_redirects(graph_edges) except ExtensionError as e: app.statuscode = 1 raise e logger.info('Writing redirects...') # write redirects for src_redirect_from, src_redirect_to in redirects.items(): # Normalize path - src_redirect_.* is relative so drive letters aren't an issue. src_redirect_from = Path(PureWindowsPath(src_redirect_from)) src_redirect_to = Path(PureWindowsPath(src_redirect_to)) # remove extensions redirect_from_name = remove_suffix( src_redirect_from.name, app.config.source_suffix ) redirect_to_name = remove_suffix(src_redirect_to.name, app.config.source_suffix) redirect_from = src_redirect_from.parent / f'{redirect_from_name}.html' redirect_to = src_redirect_to.parent / f'{redirect_to_name}.html' if type(app.builder) is DirectoryHTMLBuilder: if redirect_from_name != 'index': redirect_from = ( src_redirect_from.parent / redirect_from_name / 'index.html' ) if redirect_to_name != 'index': redirect_to = src_redirect_to.parent / redirect_to_name / 'index.html' # absolute paths into the build dir build_redirect_from = Path(app.outdir) / redirect_from build_redirect_to = Path(app.outdir) / redirect_to if ( build_redirect_from.exists() and src_redirect_from.as_posix() in redirect_record ): # if it is still pointing to the same source, continue if ( redirect_record[src_redirect_from.as_posix()] == src_redirect_to.as_posix() ): continue # otherwise remove and rewrite build_redirect_from.unlink() if build_redirect_from.exists(): logger.warning( '%s %s redirects to %s but %s already exists!', yellow('(broken)'), redirect_from, redirect_to, build_redirect_from, ) app.statuscode = 1 continue if not build_redirect_to.exists(): logger.warning( '%s %s redirects to %s but %s does not exist!', yellow('(broken)'), redirect_from, redirect_to, build_redirect_to, ) app.statuscode = 1 continue build_redirect_from.parent.mkdir(parents=True, exist_ok=True) with build_redirect_from.open('w', encoding='utf-8') as f: f.write( rediraffe_template.render( rel_url=str( PurePosixPath( PureWindowsPath( relpath(build_redirect_to, build_redirect_from.parent) ) ) ), from_file=src_redirect_from, to_file=src_redirect_to, from_url=redirect_from, to_url=redirect_to, ) ) logger.info( '%s %s %s %s', green('(good)'), redirect_from, green('-->'), redirect_to ) redirect_record[src_redirect_from.as_posix()] = src_redirect_to.as_posix() redirect_json_file.write_text(json.dumps(redirect_record), encoding='utf8') class CheckRedirectsDiffBuilder(Builder): name = 'rediraffecheckdiff' def init(self) -> None: super().init() source_suffixes = set(self.app.config.source_suffix) src_path = Path(self.app.srcdir) rediraffe_redirects = self.app.config.rediraffe_redirects redirects_path = None if isinstance(rediraffe_redirects, dict): pass elif isinstance(rediraffe_redirects, str): redirects_path = Path(src_path) / rediraffe_redirects if not redirects_path.is_file(): logger.error(red('rediraffe: rediraffe_redirects file does not exist.')) self.app.statuscode = 1 return try: rediraffe_redirects = create_graph(redirects_path) except ExtensionError: self.app.statuscode = 1 return else: logger.error('rediraffe: rediraffe was not given redirects to process.') self.app.statuscode = 1 return absolute_redirects = { (src_path / redirect_from).resolve(): (src_path / redirect_to).resolve() for redirect_from, redirect_to in rediraffe_redirects.items() } path_to_git_repo = subprocess.check_output( ('git', 'rev-parse', '--show-toplevel'), cwd=self.app.srcdir, encoding='utf-8', ) def abs_path_in_src_dir_w_src_suffix(filename: str) -> Path | None: abs_path = (Path(path_to_git_repo.strip()) / filename.strip()).resolve() if not str(abs_path).startswith(str(src_path)): return None if abs_path.suffix not in source_suffixes: return None return abs_path # run git diff cmd = ('git', 'diff', '--name-status', '--diff-filter=R') if rediraffe_branch := self.app.config.rediraffe_branch: cmd += (rediraffe_branch.strip(),) renamed_files_out = subprocess.check_output( cmd, cwd=self.app.srcdir, encoding='utf-8' ).splitlines() rename_hints = {} for line in renamed_files_out: line = line.strip() r_perc, rename_from, rename_to = re.split(r'\t', line) perc = int(r_perc[1:]) path_rename_from = abs_path_in_src_dir_w_src_suffix(rename_from) path_rename_to = abs_path_in_src_dir_w_src_suffix(rename_to) if path_rename_from is None: continue if path_rename_to is None: continue rename_hints[path_rename_from] = (path_rename_to, perc) # run git diff cmd = ('git', 'diff', '--diff-filter=D', '--name-only') if rediraffe_branch := self.app.config.rediraffe_branch: cmd += (rediraffe_branch.strip(),) deleted_files = subprocess.check_output( cmd, cwd=self.app.srcdir, encoding='utf-8' ).splitlines() # to absolute path + filter out deleted_files = [ abs_path_in_src_dir_w_src_suffix(filename) for filename in deleted_files ] deleted_files = list(filter(lambda x: x is not None, deleted_files)) for deleted_file in deleted_files: if deleted_file in absolute_redirects: logger.info( 'deleted file %s redirects to %s.', deleted_file, absolute_redirects[deleted_file], ) else: err_msg = f'{red("(broken)")} {deleted_file} was deleted but is not redirected!' logger.error(err_msg) self.app.statuscode = 1 for renamed_file in rename_hints: hint_to, perc = rename_hints[renamed_file] if renamed_file in absolute_redirects: logger.info( 'renamed file %s redirects to %s.', renamed_file, absolute_redirects[renamed_file], ) continue if self.name == 'rediraffewritediff': if perc >= self.app.config.rediraffe_auto_redirect_perc: rel_rename_from = ( f'"{str(PurePosixPath(renamed_file.relative_to(src_path)))}"' ) rel_rename_to = ( f'"{str(PurePosixPath(hint_to.relative_to(src_path)))}"' ) with redirects_path.open('a', encoding='utf-8') as redirects_file: redirects_file.write(f'{rel_rename_from} {rel_rename_to}\n') logger.info( '%s Renamed file %s has been redirected to %s in your redirects file!', green('(okay)'), rel_rename_from, rel_rename_to, ) continue err_msg = ( f'{red("(broken)")} {renamed_file} was deleted but is not redirected!' f' Hint: This file was renamed to {hint_to} with a similarity of {perc}%.' ) logger.error(err_msg) self.app.statuscode = 1 def get_outdated_docs(self): return [] def prepare_writing(self=None, docnames=None): pass def write_doc(self, docname=None, doctree=None): pass def get_target_uri(self, docname=None, typ=None): return '' def read(self): return [] class WriteRedirectsDiffBuilder(CheckRedirectsDiffBuilder): name = 'rediraffewritediff' def init(self) -> None: rediraffe_redirects = self.app.config.rediraffe_redirects if not isinstance(rediraffe_redirects, str): logger.error( '%s Automatic redirects is only available with a redirects file.', red('(broken)'), ) self.app.statuscode = 1 return super().init() def setup(app: Sphinx) -> ExtensionMetadata: app.add_config_value('rediraffe_redirects', None, None) app.add_config_value('rediraffe_branch', '', None) app.add_config_value('rediraffe_template', None, None) app.add_config_value('rediraffe_auto_redirect_perc', 100, None) app.add_builder(CheckRedirectsDiffBuilder) app.add_builder(WriteRedirectsDiffBuilder) app.connect('build-finished', build_redirects) return { 'version': __version__, 'env_version': 1, 'parallel_read_safe': True, 'parallel_write_safe': True, } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4531574 sphinxext_rediraffe-0.3.0/tests/conftest.py0000644000000000000000000001100015066252326016041 0ustar00from __future__ import annotations import os import shutil import stat import subprocess from contextlib import suppress from pathlib import Path import pytest import sphinx from seleniumbase import config as sb_config if sphinx.version_info[:2] >= (7, 2): TESTS_ROOT = Path(__file__).resolve().parent else: from sphinx.testing.path import path TESTS_ROOT = path(__file__).abspath().parent pytest_plugins = ['sphinx.testing.fixtures'] def del_rw(action, name, exc): os.chmod(name, stat.S_IWRITE) os.remove(name) def delete(path: str | Path): path = Path(path).resolve() if path.exists(): if path.is_dir(): shutil.rmtree(path, onerror=del_rw) else: try: path.unlink() except Exception: del_rw(None, path, None) # @pytest.fixture(scope="session") # def rootdir(): # return TESTS_ROOT / "roots" @pytest.fixture def content(app): app.build() return app @pytest.fixture def outdir(app): return app.outdir @pytest.fixture def app_init_repo(make_app, app_params): """ Initializes a git repo before returning the app. The files in the specified test root are converted into a git repo. For example, in a test root with folders: HEAD, HEAD~1, HEAD~2, the files in each folder are treated as a snapshot of a git repo at their respective revs. A git repo is created and in order: 1. HEAD~2's files are moved to the parent and are commited 2. HEAD~1's files are moved to the parent and are commited 3. HEAD's files are moved to the parent and are commited Returns: app: Sphinx app; same as the `app` fixture """ args, kwargs = app_params srcdir = None if 'srcdir' in kwargs: srcdir = kwargs['srcdir'] elif 'buildername' in kwargs: srcdir = args[1] else: srcdir = args[0] print(srcdir) src_path = Path(srcdir) def git(*cmd: str): with suppress(subprocess.CalledProcessError): subprocess.check_output( ( 'git', '-c', 'user.name="sphinxext-linkcheckdiff test runner"', '-c', 'user.email="NONE"', *cmd, ), cwd=src_path, ) git('init') src_item_paths = list(src_path.glob('*')) commits = [] for item_path in src_item_paths: if not item_path.name.startswith('HEAD'): continue commit_num = None sq_idx = item_path.name.find('~') if sq_idx != -1: commit_num = int(item_path.name[sq_idx + 1 :]) else: commit_num = 0 commits.append((item_path, commit_num)) commits.sort(key=lambda tup: tup[1], reverse=True) for commit in commits: files = list(src_path.glob('*')) for file in files: if file not in src_item_paths: delete(file) for file in (src_path / commit[0]).glob('*'): new_path = file.parent.parent / file.name file.rename(new_path) git('add', '.') for path in src_item_paths: git('rm', '--cached', '-r', path) git('commit', '-m', f'Apply {commit[0]}') delete(src_path / commit[0]) return make_app(*args, **kwargs) def pytest_configure(config): config.addinivalue_line('markers', 'sphinx') def rel2url(outdir, path): return 'file://' + str((Path(outdir) / path).resolve()) @pytest.fixture(scope='session') def sb_(request): """Same as the sb fixture but with a session scope""" from seleniumbase import BaseCase class BaseClass(BaseCase): def setUp(self): super().setUp() def tearDown(self): self.save_teardown_screenshot() super().tearDown() def base_method(self): pass sb = BaseClass('base_method') sb.setUp() sb._needs_tearDown = True sb_config._sb_node[request.node.nodeid] = sb yield sb if sb._needs_tearDown: sb.tearDown() sb._needs_tearDown = False @pytest.fixture def ensure_redirect(outdir, sb_): # outdir = app.outdir def _ensure_redirect(before: str, expected_after: str): before_url = rel2url(outdir, before) sb_.open(before_url) expected_after_path = Path(rel2url(outdir, expected_after)) actual_after_path = Path(sb_.get_current_url()) assert actual_after_path == expected_after_path return _ensure_redirect ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4531574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD/docs/folder1/f1.rst0000644000000000000000000000000215066252326025723 0ustar00f1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4531574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD/docs/folder2/f2.rst0000644000000000000000000000000215066252326025725 0ustar00f2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4531574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD/index.rst0000644000000000000000000000001215066252326024241 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4531574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD/redirects.txt0000644000000000000000000000034315066252326025134 0ustar00tof1.rst docs\folder1\f1.rst docs\folder1\tof1.rst docs\folder1\f1.rst docs\folder1\tof2.rst docs\folder2\f2.rst docs\folder2\toindex.rst index.rst totoindex.rst docs\folder2\toindex.rst ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4531574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD~1/docs/folder1/f1.rst0000644000000000000000000000000215066252326026202 0ustar00f1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD~1/docs/folder1/tof1.rst0000644000000000000000000000000415066252326026547 0ustar00tof1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD~1/docs/folder1/tof2.rst0000644000000000000000000000000415066252326026550 0ustar00tof2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD~1/docs/folder2/f2.rst0000644000000000000000000000000215066252326026204 0ustar00f2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD~1/docs/folder2/toindex.rst0000644000000000000000000000000715066252326027354 0ustar00toindex././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD~1/index.rst0000644000000000000000000000001215066252326024520 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD~1/redirects.txt0000644000000000000000000000000015066252326025401 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD~1/tof1.rst0000644000000000000000000000000415066252326024263 0ustar00tof1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/HEAD~1/totoindex.rst0000644000000000000000000000001115066252326025425 0ustar00totoindex././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-backslashes/conf.py0000644000000000000000000000027215066252326023206 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-bad_rediraffe_file/HEAD/another2.rst0000644000000000000000000000001415066252326026127 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-bad_rediraffe_file/HEAD/index.rst0000644000000000000000000000001215066252326025512 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-bad_rediraffe_file/HEAD/redirects.txt0000644000000000000000000000003015066252326026376 0ustar00another.rst another2.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-bad_rediraffe_file/HEAD~1/another.rst0000644000000000000000000000001415066252326026324 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-bad_rediraffe_file/HEAD~1/index.rst0000644000000000000000000000001215066252326025771 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-bad_rediraffe_file/HEAD~1/redirects.txt0000644000000000000000000000000015066252326026652 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-bad_rediraffe_file/conf.py0000644000000000000000000000033415066252326024456 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = 'not-a-redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected/HEAD/index.rst0000644000000000000000000000001215066252326027435 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected/HEAD/redirects.txt0000644000000000000000000000000015066252326030316 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected/HEAD~1/another.rst0000644000000000000000000000001415066252326030247 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected/HEAD~1/index.rst0000644000000000000000000000001215066252326027714 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected/HEAD~1/redirects.txt0000644000000000000000000000000015066252326030575 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected/conf.py0000644000000000000000000000032615066252326026402 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected_commit/HEAD/index.rst0000644000000000000000000000001215066252326031005 0ustar00index file././@PaxHeader0000000000000000000000000000021600000000000010214 xustar00114 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected_commit/HEAD/redirects.txt 28 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected_commit/HEAD/redirects0000644000000000000000000000000015066252326031050 0ustar00././@PaxHeader0000000000000000000000000000021600000000000010214 xustar00114 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected_commit/HEAD~1/another.rst 28 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected_commit/HEAD~1/another0000644000000000000000000000001415066252326031010 0ustar00another file././@PaxHeader0000000000000000000000000000021400000000000010212 xustar00112 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected_commit/HEAD~1/index.rst 28 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected_commit/HEAD~1/index.r0000644000000000000000000000001215066252326030715 0ustar00index file././@PaxHeader0000000000000000000000000000022000000000000010207 xustar00116 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected_commit/HEAD~1/redirects.txt 28 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected_commit/HEAD~1/redirec0000644000000000000000000000000015066252326030760 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4541574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_not_redirected_commit/conf.py0000644000000000000000000000054315066252326027753 0ustar00from __future__ import annotations import subprocess from pathlib import Path extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' rediraffe_branch = subprocess.check_output( ('git', 'rev-parse', 'HEAD~1'), cwd=Path(__file__).parent ).decode('utf-8') ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected/HEAD/index.rst0000644000000000000000000000001215066252326026555 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected/HEAD/redirects.txt0000644000000000000000000000002515066252326027445 0ustar00another.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected/HEAD~1/another.rst0000644000000000000000000000001415066252326027367 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected/HEAD~1/index.rst0000644000000000000000000000001215066252326027034 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected/HEAD~1/redirects.txt0000644000000000000000000000000015066252326027715 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected/conf.py0000644000000000000000000000032615066252326025522 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected_commit/HEAD/index.rst0000644000000000000000000000001215066252326030125 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected_commit/HEAD/redirects.txt0000644000000000000000000000002515066252326031015 0ustar00another.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected_commit/HEAD~1/another.rst0000644000000000000000000000001415066252326030737 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected_commit/HEAD~1/index.rst0000644000000000000000000000001215066252326030404 0ustar00index file././@PaxHeader0000000000000000000000000000021400000000000010212 xustar00112 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected_commit/HEAD~1/redirects.txt 28 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected_commit/HEAD~1/redirects.t0000644000000000000000000000000015066252326030711 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected_commit/conf.py0000644000000000000000000000054315066252326027073 0ustar00from __future__ import annotations import subprocess from pathlib import Path extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' rediraffe_branch = subprocess.check_output( ('git', 'rev-parse', 'HEAD~1'), cwd=Path(__file__).parent ).decode('utf-8') ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected_dict/HEAD/conf.py0000644000000000000000000000035215066252326027225 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = { 'another.rst': 'index.rst', } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected_dict/HEAD/index.rst0000644000000000000000000000001215066252326027560 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected_dict/HEAD~1/another.rst0000644000000000000000000000001415066252326030372 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected_dict/HEAD~1/conf.py0000644000000000000000000000031115066252326027477 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = {} ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-deleted_file_redirected_dict/HEAD~1/index.rst0000644000000000000000000000001215066252326030037 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-file_changed/HEAD/index.rst0000644000000000000000000000002615066252326024353 0ustar00index file but changed././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-file_changed/HEAD/redirects.txt0000644000000000000000000000000015066252326025227 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-file_changed/HEAD~1/index.rst0000644000000000000000000000001215066252326024625 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-file_changed/HEAD~1/redirects.txt0000644000000000000000000000000015066252326025506 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-file_changed/conf.py0000644000000000000000000000032615066252326023313 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_to_chain/HEAD/index.rst0000644000000000000000000000001215066252326026751 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4551575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_to_chain/HEAD/redirects.txt0000644000000000000000000000005715066252326027646 0ustar00another.rst another2.rst another2.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_to_chain/HEAD~1/another.rst0000644000000000000000000000001415066252326027563 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_to_chain/HEAD~1/another2.rst0000644000000000000000000000001415066252326027645 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_to_chain/HEAD~1/index.rst0000644000000000000000000000001215066252326027230 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_to_chain/HEAD~1/redirects.txt0000644000000000000000000000000015066252326030111 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_to_chain/conf.py0000644000000000000000000000032615066252326025716 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_twice/HEAD/another2.rst0000644000000000000000000000001115066252326026712 0ustar00another 2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_twice/HEAD/index.rst0000644000000000000000000000001215066252326026300 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_twice/HEAD/redirects.txt0000644000000000000000000000005615066252326027174 0ustar00another.rst index.rst another.rst another2.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_twice/HEAD~1/another2.rst0000644000000000000000000000001115066252326027171 0ustar00another 2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_twice/HEAD~1/index.rst0000644000000000000000000000001215066252326026557 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_twice/HEAD~1/redirects.txt0000644000000000000000000000002515066252326027447 0ustar00another.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-link_redirected_twice/conf.py0000644000000000000000000000032615066252326025245 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD/docs/folder1/f1.rst0000644000000000000000000000000215066252326026270 0ustar00f1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD/docs/folder2/f2.rst0000644000000000000000000000000215066252326026272 0ustar00f2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD/index.rst0000644000000000000000000000001215066252326024606 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD/redirects.txt0000644000000000000000000000034315066252326025501 0ustar00tof1.rst docs\folder1\f1.rst docs\folder1\tof1.rst docs/folder1\f1.rst docs/folder1/tof2.rst docs\folder2/f2.rst docs\folder2/toindex.rst index.rst totoindex.rst docs/folder2/toindex.rst ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD~1/docs/folder1/f1.rst0000644000000000000000000000000215066252326026547 0ustar00f1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD~1/docs/folder1/tof1.rst0000644000000000000000000000000415066252326027114 0ustar00tof1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD~1/docs/folder1/tof2.rst0000644000000000000000000000000415066252326027115 0ustar00tof2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD~1/docs/folder2/f2.rst0000644000000000000000000000000215066252326026551 0ustar00f2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD~1/docs/folder2/toindex.rst0000644000000000000000000000000715066252326027721 0ustar00toindex././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD~1/index.rst0000644000000000000000000000001215066252326025065 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD~1/redirects.txt0000644000000000000000000000000015066252326025746 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD~1/tof1.rst0000644000000000000000000000000415066252326024630 0ustar00tof1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/HEAD~1/totoindex.rst0000644000000000000000000000001115066252326025772 0ustar00totoindex././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4561574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-mixed_slashes/conf.py0000644000000000000000000000027215066252326023553 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD/docs/folder1/f1.rst0000644000000000000000000000000215066252326024722 0ustar00f1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD/docs/folder2/f2.rst0000644000000000000000000000000215066252326024724 0ustar00f2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD/index.rst0000644000000000000000000000001215066252326023240 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD/redirects.txt0000644000000000000000000000034315066252326024133 0ustar00tof1.rst docs/folder1/f1.rst docs/folder1/tof1.rst docs/folder1/f1.rst docs/folder1/tof2.rst docs/folder2/f2.rst docs/folder2/toindex.rst index.rst totoindex.rst docs/folder2/toindex.rst ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD~1/docs/folder1/f1.rst0000644000000000000000000000000215066252326025201 0ustar00f1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD~1/docs/folder1/tof1.rst0000644000000000000000000000000415066252326025546 0ustar00tof1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD~1/docs/folder1/tof2.rst0000644000000000000000000000000415066252326025547 0ustar00tof2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD~1/docs/folder2/f2.rst0000644000000000000000000000000215066252326025203 0ustar00f2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD~1/docs/folder2/toindex.rst0000644000000000000000000000000715066252326026353 0ustar00toindex././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD~1/index.rst0000644000000000000000000000001215066252326023517 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD~1/redirects.txt0000644000000000000000000000000015066252326024400 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD~1/tof1.rst0000644000000000000000000000000415066252326023262 0ustar00tof1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/HEAD~1/totoindex.rst0000644000000000000000000000001115066252326024424 0ustar00totoindex././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-nested/conf.py0000644000000000000000000000027215066252326022205 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_not_redirected/HEAD/another2.rst0000644000000000000000000000001415066252326030057 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_not_redirected/HEAD/index.rst0000644000000000000000000000001215066252326027442 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_not_redirected/HEAD/redirects.txt0000644000000000000000000000000015066252326030323 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_not_redirected/HEAD~1/another.rst0000644000000000000000000000001415066252326030254 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_not_redirected/HEAD~1/index.rst0000644000000000000000000000001215066252326027721 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_not_redirected/HEAD~1/redirects.txt0000644000000000000000000000000015066252326030602 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_not_redirected/conf.py0000644000000000000000000000032615066252326026407 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_redirected/HEAD/another2.rst0000644000000000000000000000001415066252326027177 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4571574 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_redirected/HEAD/index.rst0000644000000000000000000000001215066252326026562 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_redirected/HEAD/redirects.txt0000644000000000000000000000003015066252326027446 0ustar00another.rst another2.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_redirected/HEAD~1/another.rst0000644000000000000000000000001415066252326027374 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_redirected/HEAD~1/index.rst0000644000000000000000000000001215066252326027041 0ustar00index file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_redirected/HEAD~1/redirects.txt0000644000000000000000000000000015066252326027722 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_file_redirected/conf.py0000644000000000000000000000032615066252326025527 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000021400000000000010212 xustar00112 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_not_redirected/HEAD/another2.rst 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_not_redirected/HEAD/another2.r0000644000000000000000000000001415066252326030722 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_not_redirected/HEAD/index.rst0000644000000000000000000000001215066252326030654 0ustar00index file././@PaxHeader0000000000000000000000000000021500000000000010213 xustar00113 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_not_redirected/HEAD/redirects.txt 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_not_redirected/HEAD/redirects.0000644000000000000000000000000015066252326030775 0ustar00././@PaxHeader0000000000000000000000000000021500000000000010213 xustar00113 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_not_redirected/HEAD~1/another.rst 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_not_redirected/HEAD~1/another.0000644000000000000000000000001415066252326030735 0ustar00another file././@PaxHeader0000000000000000000000000000021300000000000010211 xustar00111 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_not_redirected/HEAD~1/index.rst 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_not_redirected/HEAD~1/index.rs0000644000000000000000000000001215066252326030747 0ustar00index file././@PaxHeader0000000000000000000000000000021700000000000010215 xustar00115 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_not_redirected/HEAD~1/redirects.txt 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_not_redirected/HEAD~1/redirect0000644000000000000000000000000015066252326031013 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_not_redirected/conf.py0000644000000000000000000000032615066252326027621 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000021300000000000010211 xustar00111 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_fail/HEAD/another2.rst 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_fail/HEAD/another2.rs0000644000000000000000000000002715066252326030724 0ustar00another file but more!././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_fail/HEAD/index.rst0000644000000000000000000000001215066252326030467 0ustar00index file././@PaxHeader0000000000000000000000000000021400000000000010212 xustar00112 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_fail/HEAD/redirects.txt 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_fail/HEAD/redirects.t0000644000000000000000000000000015066252326030774 0ustar00././@PaxHeader0000000000000000000000000000021400000000000010212 xustar00112 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_fail/HEAD~1/another.rst 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_fail/HEAD~1/another.r0000644000000000000000000000001415066252326030732 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_fail/HEAD~1/index.rst0000644000000000000000000000001215066252326030746 0ustar00index file././@PaxHeader0000000000000000000000000000021600000000000010214 xustar00114 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_fail/HEAD~1/redirects.txt 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_fail/HEAD~1/redirects0000644000000000000000000000000015066252326031011 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_fail/conf.py0000644000000000000000000000032615066252326027434 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000021300000000000010211 xustar00111 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_pass/HEAD/another2.rst 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_pass/HEAD/another2.rs0000644000000000000000000000006015066252326030754 0ustar00another file and this is some additional content././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_pass/HEAD/index.rst0000644000000000000000000000001215066252326030522 0ustar00index file././@PaxHeader0000000000000000000000000000021400000000000010212 xustar00112 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_pass/HEAD/redirects.txt 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_pass/HEAD/redirects.t0000644000000000000000000000000015066252326031027 0ustar00././@PaxHeader0000000000000000000000000000021400000000000010212 xustar00112 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_pass/HEAD~1/another.rst 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_pass/HEAD~1/another.r0000644000000000000000000000004515066252326030771 0ustar00another file and this is some content././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_pass/HEAD~1/index.rst0000644000000000000000000000001215066252326031001 0ustar00index file././@PaxHeader0000000000000000000000000000021600000000000010214 xustar00114 path=sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_pass/HEAD~1/redirects.txt 28 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_pass/HEAD~1/redirects0000644000000000000000000000000015066252326031044 0ustar00././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4581575 sphinxext_rediraffe-0.3.0/tests/roots/builder/test-renamed_write_file_perc_low_pass/conf.py0000644000000000000000000000037015066252326027466 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_branch = 'HEAD~1' rediraffe_redirects = 'redirects.txt' rediraffe_auto_redirect_perc = 50 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-backslashes/conf.py0000644000000000000000000000027215066252326022360 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-backslashes/docs/folder1/f1.rst0000644000000000000000000000000215066252326024374 0ustar00f1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-backslashes/docs/folder2/f2.rst0000644000000000000000000000000215066252326024376 0ustar00f2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-backslashes/index.rst0000644000000000000000000000001215066252326022712 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-backslashes/redirects.txt0000644000000000000000000000034315066252326023605 0ustar00tof1.rst docs\folder1\f1.rst docs\folder1\tof1.rst docs\folder1\f1.rst docs\folder1\tof2.rst docs\folder2\f2.rst docs\folder2\toindex.rst index.rst totoindex.rst docs\folder2\toindex.rst ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-bad_rediraffe_file/conf.py0000644000000000000000000000027715066252326023636 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'fake-redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-bad_rediraffe_file/index.rst0000644000000000000000000000001215066252326024163 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex/conf.py0000644000000000000000000000027215066252326021544 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex/e.rst0000644000000000000000000000000115066252326021211 0ustar00e././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex/index.rst0000644000000000000000000000001215066252326022076 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex/j.rst0000644000000000000000000000000115066252326021216 0ustar00j././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex/l.rst0000644000000000000000000000000115066252326021220 0ustar00l././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex/o.rst0000644000000000000000000000000115066252326021223 0ustar00o././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex/redirects.txt0000644000000000000000000000077715066252326023004 0ustar00f.rst c.rst q.rst w.rst F2/1.rst x.rst c.rst d.rst i.rst j.rst k.rst l.rst r.rst w.rst m.rst n.rst n.rst o.rst u.rst w.rst F1/1.rst F1/2.rst t.rst w.rst b.rst c.rst g.rst d.rst h.rst g.rst p.rst z.rst a.rst b.rst d.rst e.rst w.rst x.rst y.rst x.rst x.rst z.rst v.rst u.rst F1/2.rst F2/1.rst s.rst w.rst F5/F4/F3/F2/F1/1.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex/z.rst0000644000000000000000000000000115066252326021236 0ustar00z././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex_dict/conf.py0000644000000000000000000000136615066252326022554 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = { 'f.rst': 'c.rst', 'q.rst': 'w.rst', 'F2/1.rst': 'x.rst', 'c.rst': 'd.rst', 'i.rst': 'j.rst', 'k.rst': 'l.rst', 'r.rst': 'w.rst', 'm.rst': 'n.rst', 'n.rst': 'o.rst', 'u.rst': 'w.rst', 'F1/1.rst': 'F1/2.rst', 't.rst': 'w.rst', 'b.rst': 'c.rst', 'g.rst': 'd.rst', 'h.rst': 'g.rst', 'p.rst': 'z.rst', 'a.rst': 'b.rst', 'd.rst': 'e.rst', 'w.rst': 'x.rst', 'y.rst': 'x.rst', 'x.rst': 'z.rst', 'v.rst': 'u.rst', 'F1/2.rst': 'F2/1.rst', 's.rst': 'w.rst', 'F5/F4/F3/F2/F1/1.rst': 'index.rst', } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex_dict/e.rst0000644000000000000000000000000115066252326022214 0ustar00e././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex_dict/index.rst0000644000000000000000000000001215066252326023101 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex_dict/j.rst0000644000000000000000000000000115066252326022221 0ustar00j././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex_dict/l.rst0000644000000000000000000000000115066252326022223 0ustar00l././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex_dict/o.rst0000644000000000000000000000000115066252326022226 0ustar00o././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex_dict/redirects.txt0000644000000000000000000000077715066252326024007 0ustar00f.rst c.rst q.rst w.rst F2/1.rst x.rst c.rst d.rst i.rst j.rst k.rst l.rst r.rst w.rst m.rst n.rst n.rst o.rst u.rst w.rst F1/1.rst F1/2.rst t.rst w.rst b.rst c.rst g.rst d.rst h.rst g.rst p.rst z.rst a.rst b.rst d.rst e.rst w.rst x.rst y.rst x.rst x.rst z.rst v.rst u.rst F1/2.rst F2/1.rst s.rst w.rst F5/F4/F3/F2/F1/1.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-complex_dict/z.rst0000644000000000000000000000000115066252326022241 0ustar00z././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-cycle/conf.py0000644000000000000000000000027215066252326021174 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-cycle/index.rst0000644000000000000000000000001215066252326021526 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-cycle/redirects.txt0000644000000000000000000000002715066252326022420 0ustar00a.rst b.rst b.rst a.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-dirhtml_user_index_files/conf.py0000644000000000000000000000027215066252326025147 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4591575 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-dirhtml_user_index_files/index.rst0000644000000000000000000000001215066252326025501 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-dirhtml_user_index_files/mydir/index.rst0000644000000000000000000000000215066252326026624 0ustar00qq././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-dirhtml_user_index_files/redirects.txt0000644000000000000000000000003315066252326026370 0ustar00another.rst mydir/index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-dot_in_filename/conf.py0000644000000000000000000000027215066252326023211 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-dot_in_filename/docs/a.b.c.rst0000644000000000000000000000000215066252326024244 0ustar00f1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-dot_in_filename/index.rst0000644000000000000000000000001215066252326023543 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-dot_in_filename/redirects.txt0000644000000000000000000000004015066252326024430 0ustar00docs/x.y.z.rst docs/a.b.c.rst ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-existing_link_redirected/another.rst0000644000000000000000000000001415066252326026023 0ustar00another file././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-existing_link_redirected/conf.py0000644000000000000000000000027215066252326025136 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-existing_link_redirected/index.rst0000644000000000000000000000001215066252326025470 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-existing_link_redirected/redirects.txt0000644000000000000000000000002515066252326026360 0ustar00another.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-jinja/conf.py0000644000000000000000000000035115066252326021166 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' rediraffe_template = 'rediraffe_template.html' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-jinja/index.rst0000644000000000000000000000001215066252326021522 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-jinja/rediraffe_template.html0000644000000000000000000000033515066252326024401 0ustar00

rel_url: {{rel_url}}

from_file: {{from_file}}

to_file: {{to_file}}

from_url: {{from_url}}

to_url: {{to_url}}

././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-jinja/redirects.txt0000644000000000000000000000002515066252326022412 0ustar00another.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-jinja_bad_path/conf.py0000644000000000000000000000035115066252326023010 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' rediraffe_template = 'rediraffe_template.html' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-jinja_bad_path/index.rst0000644000000000000000000000001215066252326023344 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-jinja_bad_path/redirects.txt0000644000000000000000000000002515066252326024234 0ustar00another.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-link_redirected_to_nonexistant_file/conf.py0000644000000000000000000000027215066252326027357 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-link_redirected_to_nonexistant_file/index.rst0000644000000000000000000000001215066252326027711 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-link_redirected_to_nonexistant_file/redirects.txt0000644000000000000000000000002415066252326030600 0ustar00another.rst fake.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-link_redirected_twice/conf.py0000644000000000000000000000027215066252326024417 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-link_redirected_twice/index.rst0000644000000000000000000000001215066252326024751 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-link_redirected_twice/index2.rst0000644000000000000000000000001415066252326025035 0ustar00Index 2 File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-link_redirected_twice/redirects.txt0000644000000000000000000000005415066252326025643 0ustar00another.rst index.rst another.rst index2.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-mixed_slashes/conf.py0000644000000000000000000000027215066252326022725 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4601574 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-mixed_slashes/docs/folder1/f1.rst0000644000000000000000000000000215066252326024741 0ustar00f1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-mixed_slashes/docs/folder2/f2.rst0000644000000000000000000000000215066252326024743 0ustar00f2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-mixed_slashes/index.rst0000644000000000000000000000001215066252326023257 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-mixed_slashes/redirects.txt0000644000000000000000000000034315066252326024152 0ustar00tof1.rst docs\folder1/f1.rst docs\folder1\tof1.rst docs/folder1\f1.rst docs/folder1\tof2.rst docs\folder2\f2.rst docs\folder2/toindex.rst index.rst totoindex.rst docs/folder2/toindex.rst ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-nested/conf.py0000644000000000000000000000027215066252326021357 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-nested/docs/folder1/f1.rst0000644000000000000000000000000215066252326023373 0ustar00f1././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-nested/docs/folder2/f2.rst0000644000000000000000000000000215066252326023375 0ustar00f2././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-nested/index.rst0000644000000000000000000000001215066252326021711 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-nested/redirects.txt0000644000000000000000000000034315066252326022604 0ustar00tof1.rst docs/folder1/f1.rst docs/folder1/tof1.rst docs/folder1/f1.rst docs/folder1/tof2.rst docs/folder2/f2.rst docs/folder2/toindex.rst index.rst totoindex.rst docs/folder2/toindex.rst ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-no_cycle/conf.py0000644000000000000000000000027215066252326021670 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-no_cycle/index.rst0000644000000000000000000000001215066252326022222 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-no_cycle/redirects.txt0000644000000000000000000000003315066252326023111 0ustar00a.rst b.rst b.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-no_rediraffe_file/conf.py0000644000000000000000000000022315066252326023513 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-no_rediraffe_file/index.rst0000644000000000000000000000001215066252326024051 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-no_redirects/conf.py0000644000000000000000000000027215066252326022555 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-no_redirects/index.rst0000644000000000000000000000001215066252326023107 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-no_redirects/redirects.txt0000644000000000000000000000002515066252326023777 0ustar00another.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-pass_url_fragments_queries/conf.py0000644000000000000000000000027215066252326025530 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-pass_url_fragments_queries/index.rst0000644000000000000000000000001215066252326026062 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-pass_url_fragments_queries/redirects.txt0000644000000000000000000000002515066252326026752 0ustar00another.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-redirect_from_deleted_folder/conf.py0000644000000000000000000000027215066252326025742 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-redirect_from_deleted_folder/index.rst0000644000000000000000000000001215066252326026274 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-redirect_from_deleted_folder/redirects.txt0000644000000000000000000000012615066252326027166 0ustar00deletedfolder/another.rst index.rst deletedfolder/deletedfolder2/another.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-simple/conf.py0000644000000000000000000000027215066252326021366 0ustar00from __future__ import annotations extensions = ['sphinxext.rediraffe'] master_doc = 'index' exclude_patterns = ['_build'] html_theme = 'basic' rediraffe_redirects = 'redirects.txt' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-simple/index.rst0000644000000000000000000000001215066252326021720 0ustar00Index File././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/roots/ext/test-simple/redirects.txt0000644000000000000000000000002515066252326022610 0ustar00another.rst index.rst././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4611576 sphinxext_rediraffe-0.3.0/tests/test_builder.py0000644000000000000000000000563515066252326016722 0ustar00from __future__ import annotations import pytest from conftest import TESTS_ROOT @pytest.fixture(scope='module') def rootdir(): return TESTS_ROOT / 'roots' / 'builder' @pytest.mark.sphinx('rediraffecheckdiff', testroot='file_changed') def test_file_changed(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 0 @pytest.mark.sphinx('rediraffecheckdiff', testroot='deleted_file_redirected') def test_builder_deleted_file_redirected(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 0 @pytest.mark.sphinx('rediraffecheckdiff', testroot='deleted_file_not_redirected') def test_builder_deleted_file_not_redirected(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 1 @pytest.mark.sphinx('rediraffecheckdiff', testroot='renamed_file_redirected') def test_builder_renamed_file_redirected(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 0 @pytest.mark.sphinx('rediraffecheckdiff', testroot='renamed_file_not_redirected') def test_builder_renamed_file_not_redirected(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 1 @pytest.mark.sphinx('rediraffecheckdiff', testroot='link_redirected_to_chain') def test_builder_link_redirected_to_chain(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 0 @pytest.mark.sphinx('rediraffecheckdiff', testroot='link_redirected_twice') def test_builder_link_redirected_twice(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 1 @pytest.mark.sphinx('rediraffecheckdiff', testroot='bad_rediraffe_file') def test_builder_bad_rediraffe_file(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 1 @pytest.mark.sphinx('rediraffecheckdiff', testroot='nested') def test_builder_nested(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 0 @pytest.mark.sphinx('rediraffecheckdiff', testroot='backslashes') def test_builder_backslashes(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 0 @pytest.mark.sphinx('rediraffecheckdiff', testroot='mixed_slashes') def test_builder_mixed_slashes(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 0 @pytest.mark.sphinx('rediraffecheckdiff', testroot='deleted_file_redirected_commit') def test_builder_deleted_file_redirected_commit(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 0 @pytest.mark.sphinx('rediraffecheckdiff', testroot='deleted_file_not_redirected_commit') def test_builder_deleted_file_not_redirected_commit(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 1 @pytest.mark.sphinx('rediraffecheckdiff', testroot='deleted_file_redirected_dict') def test_builder_deleted_file_redirected_dict(app_init_repo): app_init_repo.build() assert app_init_repo.statuscode == 0 ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4621575 sphinxext_rediraffe-0.3.0/tests/test_create_graph.py0000644000000000000000000001134315066252326017711 0ustar00from __future__ import annotations import pytest from sphinx.errors import ExtensionError from sphinxext.rediraffe import create_graph def test_create_graph(tmp_path): path = tmp_path / 'rediraffe.txt' path.write_text( """ a b c d d e """, encoding='utf-8', ) graph = create_graph(path) assert graph == { 'a': 'b', 'c': 'd', 'd': 'e', } def test_create_graph_spacing(tmp_path): path = tmp_path / 'rediraffe.txt' path.write_text( """ a b c d d e """, encoding='utf-8', ) graph = create_graph(path) assert graph == { 'a': 'b', 'c': 'd', 'd': 'e', } def test_create_graph_link_redirected_twice(tmp_path): path = tmp_path / 'rediraffe.txt' path.write_text( """ a b a c """, encoding='utf-8', ) with pytest.raises(ExtensionError): create_graph(path) def test_create_graph_link_redirected_lots(tmp_path): path = tmp_path / 'rediraffe.txt' path.write_text( """ a b c d a c d e a q """, encoding='utf-8', ) with pytest.raises(ExtensionError): create_graph(path) class TestCreateGraphQuotes: def test_no_quotes(self, tmp_path): path = tmp_path / 'rediraffe.txt' path.write_text( """ a b c d d e """, encoding='utf-8', ) graph = create_graph(path) assert graph == { 'a': 'b', 'c': 'd', 'd': 'e', } def test_single_quotes(self, tmp_path): path = tmp_path / 'rediraffe.txt' path.write_text( """ 'a' b c 'd' d e """, encoding='utf-8', ) graph = create_graph(path) assert graph == { 'a': 'b', 'c': 'd', 'd': 'e', } def test_both_single_quotes(self, tmp_path): path = tmp_path / 'rediraffe.txt' path.write_text( """ 'a' 'b' 'c' 'd' d e """, encoding='utf-8', ) graph = create_graph(path) assert graph == { 'a': 'b', 'c': 'd', 'd': 'e', } def test_commented(self, tmp_path): path = tmp_path / 'rediraffe.txt' path.write_text( """ # a comment a b c d # another comment d e """, encoding='utf-8', ) graph = create_graph(path) assert graph == { 'a': 'b', 'c': 'd', 'd': 'e', } def test_double_quotes(self, tmp_path): path = tmp_path / 'rediraffe.txt' path.write_text( """ "a" b c "d" d e """, encoding='utf-8', ) graph = create_graph(path) assert graph == { 'a': 'b', 'c': 'd', 'd': 'e', } def test_both_double_quotes(self, tmp_path): path = tmp_path / 'rediraffe.txt' path.write_text( """ "a" "b" "c" "d" d e """, encoding='utf-8', ) graph = create_graph(path) assert graph == { 'a': 'b', 'c': 'd', 'd': 'e', } def test_quote_in_path(self, tmp_path): path = tmp_path / 'rediraffe.txt' path.write_text( """ "a b c d' d "e "e' f'" """, encoding='utf-8', ) graph = create_graph(path) assert graph == { '"a': 'b', 'c': "d'", 'd': '"e', '"e\'': 'f\'"', } def test_complex(self, tmp_path): path = tmp_path / 'rediraffe.txt' path.write_text( """ "Double Quoted Path" 'Single Quoted Path' "Website's Contents" "other" 'Store's Contents' other "quoteskept' "other" ""I'm ready! I'm ready!" - Spongebob Squarepants.rst" "just why?.rst" """, encoding='utf-8', ) graph = create_graph(path) assert graph == { 'Double Quoted Path': 'Single Quoted Path', "Website's Contents": 'other', "Store's Contents": 'other', '"quoteskept\'': 'other', '"I\'m ready! I\'m ready!" - Spongebob Squarepants.rst': 'just why?.rst', } ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4621575 sphinxext_rediraffe-0.3.0/tests/test_create_simple_redirects.py0000644000000000000000000000400715066252326022144 0ustar00from __future__ import annotations import pytest from sphinx.errors import ExtensionError from sphinxext.rediraffe import create_simple_redirects def test_create_simple_redirects_empty(): assert create_simple_redirects({}) == {} def test_create_simple_redirects_no_cycle(): simple_redirects = redirects = { 'a': 'b', } assert create_simple_redirects(redirects) == simple_redirects def test_create_simple_redirects_simple_cycle(): redirects = { 'a': 'b', 'b': 'a', } with pytest.raises(ExtensionError): create_simple_redirects(redirects) def test_create_simple_redirects_complex_cycles(): redirects = { 'a': 'b', 'b': 'c', 'c': 'd', 'd': 'e', 'e': 'a', } with pytest.raises(ExtensionError): create_simple_redirects(redirects) def test_create_simple_redirects_multiple_cycles(): redirects = { 'a': 'b', 'b': 'c', 'c': 'd', 'd': 'e', 'e': 'a', 'f': 'g', 'g': 'h', 'h': 'j', 'j': 'g', } with pytest.raises(ExtensionError): create_simple_redirects(redirects) def test_create_simple_redirects_no_chains(): simple_redirects = redirects = { 'a': 'b', 'c': 'd', 'e': 'f', } assert create_simple_redirects(redirects) == simple_redirects def test_create_simple_redirects_chain(): redirects = { 'a': 'b', 'b': 'c', 'c': 'd', } simple_redirects = { 'a': 'd', 'b': 'd', 'c': 'd', } assert create_simple_redirects(redirects) == simple_redirects def test_create_simple_redirects_mixed_chains(): redirects = { 'a': 'b', 'b': 'c', 'c': 'd', 'e': 'f', 'g': 'h', 'h': 'i', } simple_redirects = { 'a': 'd', 'b': 'd', 'c': 'd', 'e': 'f', 'g': 'i', 'h': 'i', } assert create_simple_redirects(redirects) == simple_redirects ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4621575 sphinxext_rediraffe-0.3.0/tests/test_ext.py0000644000000000000000000005162315066252326016072 0ustar00from __future__ import annotations import shutil from pathlib import Path import pytest from conftest import TESTS_ROOT, rel2url from sphinx.errors import ExtensionError TYPE_CHECKING = False if TYPE_CHECKING: from seleniumbase import BaseCase from sphinx.application import Sphinx @pytest.fixture(scope='module') def rootdir(): return TESTS_ROOT / 'roots' / 'ext' class TestExtHtml: @pytest.mark.sphinx('html', testroot='no_redirects') def test_no_redirects(self, app: Sphinx): app.build() assert app.statuscode == 0 @pytest.mark.sphinx('html', testroot='simple') def test_simple(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('another.html', 'index.html') @pytest.mark.sphinx('html', testroot='simple') def test_simple_rebuild(self, app_params, make_app, ensure_redirect): args, kwargs = app_params app = make_app(*args, **kwargs) if Path(app.outdir).exists(): shutil.rmtree(Path(app.outdir)) app.build() assert app.statuscode == 0 app2 = make_app(*args, **kwargs) app2.build() assert app2.statuscode == 0 ensure_redirect('another.html', 'index.html') @pytest.mark.sphinx('html', testroot='no_cycle') def test_no_cycle(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('a.html', 'index.html') ensure_redirect('b.html', 'index.html') @pytest.mark.sphinx('html', testroot='cycle') def test_cycle(self, app: Sphinx): with pytest.raises(ExtensionError): app.build() assert app.statuscode == 1 @pytest.mark.sphinx('html', testroot='nested') def test_nested(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('tof1.html', 'docs/folder1/f1.html') ensure_redirect('docs/folder1/tof1.html', 'docs/folder1/f1.html') ensure_redirect('docs/folder1/tof2.html', 'docs/folder2/f2.html') ensure_redirect('docs/folder2/toindex.html', 'index.html') ensure_redirect('totoindex.html', 'index.html') @pytest.mark.sphinx('html', testroot='backslashes') def test_backslashes(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('tof1.html', 'docs/folder1/f1.html') ensure_redirect('docs/folder1/tof1.html', 'docs/folder1/f1.html') ensure_redirect('docs/folder1/tof2.html', 'docs/folder2/f2.html') ensure_redirect('docs/folder2/toindex.html', 'index.html') ensure_redirect('totoindex.html', 'index.html') @pytest.mark.sphinx('html', testroot='dot_in_filename') def test_dot_in_filename(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('docs/x.y.z.html', 'docs/a.b.c.html') @pytest.mark.sphinx('html', testroot='mixed_slashes') def test_mixed_slashes(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('tof1.html', 'docs/folder1/f1.html') ensure_redirect('docs/folder1/tof1.html', 'docs/folder1/f1.html') ensure_redirect('docs/folder1/tof2.html', 'docs/folder2/f2.html') ensure_redirect('docs/folder2/toindex.html', 'index.html') ensure_redirect('totoindex.html', 'index.html') @pytest.mark.sphinx('html', testroot='link_redirected_twice') def test_link_redirected_twice(self, app: Sphinx): with pytest.raises(ExtensionError): app.build() assert app.statuscode == 1 @pytest.mark.sphinx('html', testroot='link_redirected_to_nonexistant_file') def test_link_redirected_to_nonexistant_file(self, app: Sphinx): app.build() assert app.statuscode == 1 @pytest.mark.sphinx('html', testroot='existing_link_redirected') def test_existing_link_redirected(self, app: Sphinx): app.build() assert app.statuscode == 1 @pytest.mark.sphinx('html', testroot='bad_rediraffe_file') def test_bad_rediraffe_file(self, app: Sphinx): app.build() assert app.statuscode == 1 @pytest.mark.sphinx('html', testroot='no_rediraffe_file') def test_no_rediraffe_file(self, app: Sphinx): app.build() assert app.statuscode == 0 assert 'rediraffe was not given redirects to process' in app._warning.getvalue() @pytest.mark.sphinx('html', testroot='redirect_from_deleted_folder') def test_redirect_from_deleted_folder(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('deletedfolder/another.html', 'index.html') ensure_redirect('deletedfolder/deletedfolder2/another.html', 'index.html') @pytest.mark.sphinx('html', testroot='complex') def test_complex(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('a.html', 'e.html') ensure_redirect('b.html', 'e.html') ensure_redirect('c.html', 'e.html') ensure_redirect('d.html', 'e.html') ensure_redirect('f.html', 'e.html') ensure_redirect('g.html', 'e.html') ensure_redirect('h.html', 'e.html') ensure_redirect('i.html', 'j.html') ensure_redirect('k.html', 'l.html') ensure_redirect('m.html', 'o.html') ensure_redirect('n.html', 'o.html') ensure_redirect('q.html', 'z.html') ensure_redirect('r.html', 'z.html') ensure_redirect('s.html', 'z.html') ensure_redirect('t.html', 'z.html') ensure_redirect('u.html', 'z.html') ensure_redirect('v.html', 'z.html') ensure_redirect('w.html', 'z.html') ensure_redirect('x.html', 'z.html') ensure_redirect('y.html', 'z.html') ensure_redirect('F1/1.html', 'z.html') ensure_redirect('F1/2.html', 'z.html') ensure_redirect('F2/1.html', 'z.html') ensure_redirect('F5/F4/F3/F2/F1/1.html', 'index.html') @pytest.mark.sphinx('html', testroot='complex_dict') def test_complex_dict(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('a.html', 'e.html') ensure_redirect('b.html', 'e.html') ensure_redirect('c.html', 'e.html') ensure_redirect('d.html', 'e.html') ensure_redirect('f.html', 'e.html') ensure_redirect('g.html', 'e.html') ensure_redirect('h.html', 'e.html') ensure_redirect('i.html', 'j.html') ensure_redirect('k.html', 'l.html') ensure_redirect('m.html', 'o.html') ensure_redirect('n.html', 'o.html') ensure_redirect('q.html', 'z.html') ensure_redirect('r.html', 'z.html') ensure_redirect('s.html', 'z.html') ensure_redirect('t.html', 'z.html') ensure_redirect('u.html', 'z.html') ensure_redirect('v.html', 'z.html') ensure_redirect('w.html', 'z.html') ensure_redirect('x.html', 'z.html') ensure_redirect('y.html', 'z.html') ensure_redirect('F1/1.html', 'z.html') ensure_redirect('F1/2.html', 'z.html') ensure_redirect('F2/1.html', 'z.html') ensure_redirect('F5/F4/F3/F2/F1/1.html', 'index.html') @pytest.mark.sphinx('html', testroot='jinja') def test_jinja(self, app: Sphinx, sb_: BaseCase): app.build() assert app.statuscode == 0 sb_.open(rel2url(app.outdir, 'another.html')) text = sb_.get_text(selector='html') text = text.replace('\\', '/') text = text.replace('//', '/') assert 'rel_url: index.html' in text assert 'from_file: another.rst' in text assert 'to_file: index.rst' in text assert 'from_url: another.html' in text assert 'to_url: index.html' in text @pytest.mark.sphinx('html', testroot='jinja_bad_path') def test_jinja_bad_path(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('another.html', 'index.html') @pytest.mark.sphinx('html', testroot='pass_url_fragments_queries') def test_pass_url_fragments(self, app: Sphinx, sb_: BaseCase, ensure_redirect): app.build() ensure_redirect('another.html', 'index.html') sb_.open(rel2url(app.outdir, 'another.html') + '#haha') # check url assert Path(rel2url(app.outdir, 'index.html')) == Path( sb_.execute_script( 'return window.location.protocol + "//" + window.location.host + "/" + window.location.pathname' ) ) # check hash assert '#haha' == sb_.execute_script('return window.location.hash') @pytest.mark.sphinx('html', testroot='pass_url_fragments_queries') def test_pass_url_queries(self, app: Sphinx, sb_: BaseCase, ensure_redirect): app.build() ensure_redirect('another.html', 'index.html') sb_.open(rel2url(app.outdir, 'another.html') + '?phrase=haha') # check url assert Path(rel2url(app.outdir, 'index.html')) == Path( sb_.execute_script( 'return window.location.protocol + "//" + window.location.host + "/" + window.location.pathname' ) ) # check query assert '?phrase=haha' == sb_.execute_script('return window.location.search') @pytest.mark.sphinx('html', testroot='pass_url_fragments_queries') def test_pass_url_fragment_and_query( self, app: Sphinx, sb_: BaseCase, ensure_redirect ): app.build() ensure_redirect('another.html', 'index.html') sb_.open(rel2url(app.outdir, 'another.html') + '?phrase=haha#giraffe') # check url assert Path(rel2url(app.outdir, 'index.html')) == Path( sb_.execute_script( 'return window.location.protocol + "//" + window.location.host + "/" + window.location.pathname' ) ) # check query assert '?phrase=haha' == sb_.execute_script('return window.location.search') # check hash assert '#giraffe' == sb_.execute_script('return window.location.hash') class TestExtDirHtml: @pytest.mark.sphinx('dirhtml', testroot='no_redirects') def test_no_redirects(self, app: Sphinx): app.build() assert app.statuscode == 0 @pytest.mark.sphinx('dirhtml', testroot='simple') def test_simple(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('another/index.html', 'index.html') @pytest.mark.sphinx('dirhtml', testroot='dirhtml_user_index_files') def test_index_file_foldering(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('another/index.html', 'mydir/index.html') @pytest.mark.sphinx('dirhtml', testroot='simple', freshenv=False) def test_simple_rebuild(self, app_params, make_app, ensure_redirect): args, kwargs = app_params app = make_app(*args, **kwargs) if Path(app.outdir).exists(): shutil.rmtree(Path(app.outdir)) app.build() assert app.statuscode == 0 app2 = make_app(*args, **kwargs) app2.build() assert app2.statuscode == 0 ensure_redirect('another/index.html', 'index.html') @pytest.mark.sphinx('dirhtml', testroot='no_cycle') def test_no_cycle(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('a/index.html', 'index.html') ensure_redirect('b/index.html', 'index.html') @pytest.mark.sphinx('dirhtml', testroot='cycle') def test_cycle(self, app: Sphinx): with pytest.raises(ExtensionError): app.build() assert app.statuscode == 1 @pytest.mark.sphinx('dirhtml', testroot='nested') def test_nested(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('tof1/index.html', 'docs/folder1/f1/index.html') ensure_redirect('docs/folder1/tof1/index.html', 'docs/folder1/f1/index.html') ensure_redirect('docs/folder1/tof2/index.html', 'docs/folder2/f2/index.html') ensure_redirect('docs/folder2/toindex/index.html', 'index.html') ensure_redirect('totoindex/index.html', 'index.html') @pytest.mark.sphinx('dirhtml', testroot='backslashes') def test_backslashes(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('tof1/index.html', 'docs/folder1/f1/index.html') ensure_redirect('docs/folder1/tof1/index.html', 'docs/folder1/f1/index.html') ensure_redirect('docs/folder1/tof2/index.html', 'docs/folder2/f2/index.html') ensure_redirect('docs/folder2/toindex/index.html', 'index.html') ensure_redirect('totoindex/index.html', 'index.html') @pytest.mark.sphinx('dirhtml', testroot='dot_in_filename') def test_dot_in_filename(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('docs/x.y.z/index.html', 'docs/a.b.c/index.html') @pytest.mark.sphinx('dirhtml', testroot='mixed_slashes') def test_mixed_slashes(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('tof1/index.html', 'docs/folder1/f1/index.html') ensure_redirect('docs/folder1/tof1/index.html', 'docs/folder1/f1/index.html') ensure_redirect('docs/folder1/tof2/index.html', 'docs/folder2/f2/index.html') ensure_redirect('docs/folder2/toindex/index.html', 'index.html') ensure_redirect('totoindex/index.html', 'index.html') @pytest.mark.sphinx('dirhtml', testroot='link_redirected_twice') def test_link_redirected_twice(self, app: Sphinx): with pytest.raises(ExtensionError): app.build() assert app.statuscode == 1 @pytest.mark.sphinx('dirhtml', testroot='link_redirected_to_nonexistant_file') def test_link_redirected_to_nonexistant_file(self, app: Sphinx): app.build() assert app.statuscode == 1 @pytest.mark.sphinx('dirhtml', testroot='existing_link_redirected') def test_existing_link_redirected(self, app: Sphinx): app.build() assert app.statuscode == 1 @pytest.mark.sphinx('dirhtml', testroot='bad_rediraffe_file') def test_bad_rediraffe_file(self, app: Sphinx): app.build() assert app.statuscode == 1 @pytest.mark.sphinx('dirhtml', testroot='no_rediraffe_file') def test_no_rediraffe_file(self, app: Sphinx): app.build() assert app.statuscode == 0 assert 'rediraffe was not given redirects to process' in app._warning.getvalue() @pytest.mark.sphinx('dirhtml', testroot='redirect_from_deleted_folder') def test_redirect_from_deleted_folder(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('deletedfolder/another/index.html', 'index.html') ensure_redirect('deletedfolder/deletedfolder2/another/index.html', 'index.html') @pytest.mark.sphinx('dirhtml', testroot='complex') def test_complex(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('a/index.html', 'e/index.html') ensure_redirect('b/index.html', 'e/index.html') ensure_redirect('c/index.html', 'e/index.html') ensure_redirect('d/index.html', 'e/index.html') ensure_redirect('f/index.html', 'e/index.html') ensure_redirect('g/index.html', 'e/index.html') ensure_redirect('h/index.html', 'e/index.html') ensure_redirect('i/index.html', 'j/index.html') ensure_redirect('k/index.html', 'l/index.html') ensure_redirect('m/index.html', 'o/index.html') ensure_redirect('n/index.html', 'o/index.html') ensure_redirect('q/index.html', 'z/index.html') ensure_redirect('r/index.html', 'z/index.html') ensure_redirect('s/index.html', 'z/index.html') ensure_redirect('t/index.html', 'z/index.html') ensure_redirect('u/index.html', 'z/index.html') ensure_redirect('v/index.html', 'z/index.html') ensure_redirect('w/index.html', 'z/index.html') ensure_redirect('x/index.html', 'z/index.html') ensure_redirect('y/index.html', 'z/index.html') ensure_redirect('F1/1/index.html', 'z/index.html') ensure_redirect('F1/2/index.html', 'z/index.html') ensure_redirect('F2/1/index.html', 'z/index.html') ensure_redirect('F5/F4/F3/F2/F1/1/index.html', 'index.html') @pytest.mark.sphinx('dirhtml', testroot='complex_dict') def test_complex_dict(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('a/index.html', 'e/index.html') ensure_redirect('b/index.html', 'e/index.html') ensure_redirect('c/index.html', 'e/index.html') ensure_redirect('d/index.html', 'e/index.html') ensure_redirect('f/index.html', 'e/index.html') ensure_redirect('g/index.html', 'e/index.html') ensure_redirect('h/index.html', 'e/index.html') ensure_redirect('i/index.html', 'j/index.html') ensure_redirect('k/index.html', 'l/index.html') ensure_redirect('m/index.html', 'o/index.html') ensure_redirect('n/index.html', 'o/index.html') ensure_redirect('q/index.html', 'z/index.html') ensure_redirect('r/index.html', 'z/index.html') ensure_redirect('s/index.html', 'z/index.html') ensure_redirect('t/index.html', 'z/index.html') ensure_redirect('u/index.html', 'z/index.html') ensure_redirect('v/index.html', 'z/index.html') ensure_redirect('w/index.html', 'z/index.html') ensure_redirect('x/index.html', 'z/index.html') ensure_redirect('y/index.html', 'z/index.html') ensure_redirect('F1/1/index.html', 'z/index.html') ensure_redirect('F1/2/index.html', 'z/index.html') ensure_redirect('F2/1/index.html', 'z/index.html') ensure_redirect('F5/F4/F3/F2/F1/1/index.html', 'index.html') @pytest.mark.sphinx('dirhtml', testroot='jinja') def test_jinja(self, app: Sphinx, sb_: BaseCase): app.build() assert app.statuscode == 0 sb_.open(rel2url(app.outdir, 'another/index.html')) text = sb_.get_text(selector='html') text = text.replace('\\', '/') text = text.replace('//', '/') assert 'rel_url: ../index.html' in text assert 'from_file: another.rst' in text assert 'to_file: index.rst' in text assert 'from_url: another/index.html' in text assert 'to_url: index.html' in text @pytest.mark.sphinx('dirhtml', testroot='jinja_bad_path') def test_jinja_bad_path(self, app: Sphinx, ensure_redirect): app.build() assert app.statuscode == 0 ensure_redirect('another/index.html', 'index.html') @pytest.mark.sphinx('dirhtml', testroot='pass_url_fragments_queries') def test_pass_url_fragments(self, app: Sphinx, sb_: BaseCase, ensure_redirect): app.build() ensure_redirect('another/index.html', 'index.html') sb_.open(rel2url(app.outdir, 'another/index.html') + '#haha') # check url assert Path(rel2url(app.outdir, 'index.html')) == Path( sb_.execute_script( 'return window.location.protocol + "//" + window.location.host + "/" + window.location.pathname' ) ) # check hash assert '#haha' == sb_.execute_script('return window.location.hash') @pytest.mark.sphinx('dirhtml', testroot='pass_url_fragments_queries') def test_pass_url_queries(self, app: Sphinx, sb_: BaseCase, ensure_redirect): app.build() ensure_redirect('another/index.html', 'index.html') sb_.open(rel2url(app.outdir, 'another/index.html') + '?phrase=haha') # check url assert Path(rel2url(app.outdir, 'index.html')) == Path( sb_.execute_script( 'return window.location.protocol + "//" + window.location.host + "/" + window.location.pathname' ) ) # check query assert '?phrase=haha' == sb_.execute_script('return window.location.search') @pytest.mark.sphinx('dirhtml', testroot='pass_url_fragments_queries') def test_pass_url_fragment_and_query( self, app: Sphinx, sb_: BaseCase, ensure_redirect ): app.build() ensure_redirect('another/index.html', 'index.html') sb_.open(rel2url(app.outdir, 'another/index.html') + '?phrase=haha#giraffe') # check url assert Path(rel2url(app.outdir, 'index.html')) == Path( sb_.execute_script( 'return window.location.protocol + "//" + window.location.host + "/" + window.location.pathname' ) ) # check query assert '?phrase=haha' == sb_.execute_script('return window.location.search') # check hash assert '#giraffe' == sb_.execute_script('return window.location.hash') ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1759073494.4621575 sphinxext_rediraffe-0.3.0/tests/test_write_builder.py0000644000000000000000000000244015066252326020123 0ustar00from __future__ import annotations import pytest from conftest import TESTS_ROOT @pytest.fixture(scope='module') def rootdir(): return TESTS_ROOT / 'roots' / 'builder' @pytest.mark.sphinx('rediraffewritediff', testroot='renamed_write_file_not_redirected') def test_builder_renamed_file_write_not_redirected(app_init_repo): app_init_repo.build() valid_string = '"another.rst" "another2.rst"' redirects_text = (app_init_repo.srcdir / 'redirects.txt').read_text( encoding='utf-8' ) assert valid_string in redirects_text @pytest.mark.sphinx('rediraffewritediff', testroot='renamed_write_file_perc_low_fail') def test_builder_renamed_file_write_perc_low_fail(app_init_repo): app_init_repo.build() valid_string = '"another.rst" "another2.rst"' redirects_text = (app_init_repo.srcdir / 'redirects.txt').read_text( encoding='utf-8' ) assert valid_string not in redirects_text @pytest.mark.sphinx('rediraffewritediff', testroot='renamed_write_file_perc_low_pass') def test_builder_renamed_file_write_perc_low_pass(app_init_repo): app_init_repo.build() valid_string = '"another.rst" "another2.rst"' redirects_text = (app_init_repo.srcdir / 'redirects.txt').read_text( encoding='utf-8' ) assert valid_string in redirects_text sphinxext_rediraffe-0.3.0/PKG-INFO0000644000000000000000000000550700000000000013546 0ustar00Metadata-Version: 2.4 Name: sphinxext-rediraffe Version: 0.3.0 Summary: Sphinx Extension that redirects non-existent pages to working pages Author-email: Vasista Vovveti Requires-Python: >=3.9 Description-Content-Type: text/x-rst License-Expression: MIT Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Plugins Classifier: Environment :: Web Environment Classifier: Framework :: Sphinx :: Extension Classifier: Intended Audience :: Developers Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python Classifier: Topic :: Documentation :: Sphinx Classifier: Topic :: Documentation Classifier: Topic :: Software Development :: Documentation Classifier: Topic :: Text Processing Classifier: Topic :: Utilities License-File: LICENCE.rst Requires-Dist: Sphinx>=6.0 Project-URL: Code, https://github.com/sphinx-doc/sphinxext-rediraffe/ Project-URL: Documentation, https://sphinxext-rediraffe.readthedocs.io/ Project-URL: Download, https://pypi.org/project/sphinxext-rediraffe/ Project-URL: Homepage, https://github.com/sphinx-doc/sphinxext-rediraffe/ Project-URL: Issue tracker, https://github.com/sphinx-doc/sphinxext-rediraffe/issues =================== sphinxext-rediraffe =================== .. image:: https://img.shields.io/pypi/v/sphinxext-rediraffe.svg :target: https://pypi.org/project/sphinxext-rediraffe/ :alt: Package on PyPI .. image:: https://github.com/sphinx-doc/sphinxext-rediraffe/actions/workflows/test.yml/badge.svg :target: https://github.com/sphinx-doc/sphinxext-rediraffe/actions :alt: Build Status .. image:: https://img.shields.io/badge/License-MIT-blue.svg :target: https://opensource.org/licenses/MIT :alt: MIT Sphinx extension to redirect files .. image:: ./assets/rediraffe_logo.svg :align: center This Sphinx extension redirects non-existent pages to working pages. Rediraffe can also check that deleted or renamed files in your git repo are redirected. Rediraffe creates a graph of all specified redirects and traverses it to point all internal urls to leaf urls. This means that chained redirects will be resolved. For example, if a config has 6 chained redirects, all 6 links will redirect directly to the final link. The end user will never experience more than 1 redirection. Note: Rediraffe supports the html and dirhtml builders. Installation ============ .. code-block:: sh python -m pip install sphinxext-rediraffe Usage ===== See the `documentation`_. .. _documentation: https://sphinxext-rediraffe.readthedocs.io/en/latest/