diff --git a/sphinx/builders/html/__init__.py b/sphinx/builders/html/__init__.py index 06917232f6b..8f351b76a12 100644 --- a/sphinx/builders/html/__init__.py +++ b/sphinx/builders/html/__init__.py @@ -40,6 +40,7 @@ from sphinx.theming import HTMLThemeFactory from sphinx.util import isurl, logging from sphinx.util._timestamps import _format_rfc3339_microseconds +from sphinx.util.console import bold from sphinx.util.display import progress_message, status_iterator from sphinx.util.docutils import new_document from sphinx.util.fileutil import copy_asset @@ -389,8 +390,9 @@ def math_renderer_name(self) -> str | None: return None def get_outdated_docs(self) -> Iterator[str]: + build_info_fname = self.outdir / '.buildinfo' try: - with open(path.join(self.outdir, '.buildinfo'), encoding="utf-8") as fp: + with open(build_info_fname, encoding="utf-8") as fp: buildinfo = BuildInfo.load(fp) if self.build_info != buildinfo: @@ -405,6 +407,21 @@ def get_outdated_docs(self) -> Iterator[str]: if self.templates: template_mtime = int(self.templates.newest_template_mtime() * 10**6) + try: + old_mtime = _last_modified_time(build_info_fname) + except Exception: + pass + else: + # Let users know they have a newer template + if template_mtime > old_mtime: + logger.info( + bold("building [html]: ") + + __( + "template %s has been changed since the previous build, " + "all docs will be rebuilt" + ), + self.templates.newest_template_name(), + ) else: template_mtime = 0 for docname in self.env.found_docs: diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py index ec75c6d96cb..74321383455 100644 --- a/sphinx/jinja2glue.py +++ b/sphinx/jinja2glue.py @@ -204,8 +204,14 @@ def render_string(self, source: str, context: dict) -> str: return self.environment.from_string(source).render(context) def newest_template_mtime(self) -> float: + return self._newest_template_mtime_name()[0] + + def newest_template_name(self) -> str: + return self._newest_template_mtime_name()[1] + + def _newest_template_mtime_name(self) -> tuple[float, str]: return max( - os.stat(os.path.join(root, sfile)).st_mtime_ns / 10**9 + (os.stat(os.path.join(root, sfile)).st_mtime_ns / 10**9, sfile) for dirname in self.pathchain for root, _dirs, files in os.walk(dirname) for sfile in files