1818#
1919# import sys
2020# sys.path.insert(0, os.path.abspath('.'))
21+
22+ import git
23+ import json
2124import os
2225import pathlib
26+ import requests
2327import shutil
2428import subprocess
2529import sys
2630
27- import git
28-
29- import requests
30-
3131
3232def setup (app ):
3333 # Add property to avoid warning.
3434 app .add_config_value ('skip_python' , None , '' )
3535
3636
37+ def download_json ():
38+ """
39+ Download the common theme options of eProsima readthedocs documentation.
40+
41+ The theme options are defined in a JSON file that is hosted in the eProsima GitHub
42+ repository with the index of all eProsima product documentation
43+ (https://github.com/eProsima/all-docs).
44+
45+ :return: dictionary.
46+ """
47+ url = "https://raw.githubusercontent.com/eProsima/all-docs/master/source/_static/json/eprosima-furo.json"
48+ ret = dict ()
49+ try :
50+ req = requests .get (url , allow_redirects = True , timeout = 10 )
51+ except requests .RequestException as e :
52+ print (
53+ "Failed to download the JSON with the eProsima theme."
54+ "Request Error: {}" .format (e )
55+ )
56+ return ret
57+ if req .status_code != 200 :
58+ print (
59+ "Failed to download the JSON with the eProsima theme."
60+ "Return code: {}" .format (req .status_code )
61+ )
62+ return ret
63+ ret = json .loads (req .content )
64+ return ret
65+
66+
3767def download_css (html_css_dir ):
3868 """
3969 Download the common theme of eProsima readthedocs documentation.
@@ -96,7 +126,25 @@ def select_css(html_css_dir):
96126
97127
98128def get_git_branch ():
99- """Get the git branch this repository is currently on."""
129+ """Get the git branch this repository is currently on.
130+
131+ On Read the Docs the repo is checked out in detached-HEAD mode, so
132+ ``git name-rev`` returns synthetic names like ``remotes/origin/external-1234``
133+ instead of the real branch. A workaround is provided using
134+ ``READTHEDOCS_VERSION_TYPE`` and ``READTHEDOCS_VERSION`` according to the build type:
135+ - ``"branch"`` builds: READTHEDOCS_VERSION is the branch name (e.g. ``"3.6.x"``) → use it.
136+ - ``"tag"`` builds: READTHEDOCS_VERSION is the tag name (e.g. ``"v3.6.0"``) → use it.
137+ - ``"external"`` (PR preview) builds: READTHEDOCS_VERSION is the PR number (e.g. ``"1241"``)
138+ which is not a valid git ref. In this case we return None so resolve_fallback_branch falls
139+ back to its default instead of generating broken GitHub URLs.
140+ - Local builds: READTHEDOCS_VERSION_TYPE is unset → fall back to git name-rev.
141+ """
142+ rtd_type = os .environ .get ("READTHEDOCS_VERSION_TYPE" )
143+ if rtd_type in ("branch" , "tag" ):
144+ return os .environ .get ("READTHEDOCS_VERSION" )
145+ if rtd_type == "external" :
146+ return None
147+
100148 path_to_here = os .path .abspath (os .path .dirname (__file__ ))
101149
102150 # Invoke git to get the current branch which we use to get the theme
@@ -110,12 +158,28 @@ def get_git_branch():
110158 return p .communicate ()[0 ].decode ().rstrip ()
111159
112160 except Exception :
113- print ('Could not get the branch' )
161+ # Local build without git or some error occurred
162+ print ("Could not get the branch" )
114163
115164 # Couldn't figure out the branch probably due to an error
116165 return None
117166
118167
168+ def resolve_fallback_branch (env_var , docs_branch , default = "master" ):
169+ """
170+ Resolve the branch to use for GitHub links.
171+
172+ Priority:
173+ 1. Environment variable ``env_var`` (e.g. FASTDDS_BRANCH)
174+ 2. Current documentation branch (``docs_branch``)
175+ 3. Hard-coded ``default``
176+
177+ This mirrors the checkout logic used in the ReadTheDocs clone block so
178+ that extlinks and the actual checkout always point at the same branch.
179+ """
180+ return os .environ .get (env_var ) or docs_branch or default
181+
182+
119183def configure_doxyfile (
120184 doxyfile_in ,
121185 doxyfile_out ,
@@ -169,6 +233,27 @@ def configure_doxyfile(
169233 )
170234)
171235
236+ # Current branch of the documentation repository — resolved once, used everywhere.
237+ docs_branch = get_git_branch ()
238+ if docs_branch :
239+ print ('Current documentation branch is "{}"' .format (docs_branch ))
240+ else :
241+ print ("Current documentation branch could not be determined; " \
242+ "GitHub links will point to default branches instead of the corresponding branch." )
243+
244+ # Resolve GitHub link branches: env var → current docs branch → default.
245+ # Computed here so they are available both in the ReadTheDocs clone block and in extlinks.
246+ fastdds_fallback_branch = resolve_fallback_branch ("FASTDDS_BRANCH" , docs_branch , "2.14.x" )
247+ fastdds_docs_fallback_branch = resolve_fallback_branch ("FASTDDS_DOCS_BRANCH" , docs_branch , "2.14.x" )
248+ fastdds_python_fallback_branch = resolve_fallback_branch ("FASTDDS_PYTHON_BRANCH" , docs_branch , "1.4.x" )
249+ fastdds_gen_fallback_branch = resolve_fallback_branch ("FASTDDS_GEN_BRANCH" , docs_branch , "3.3.x" )
250+
251+ print ("Fallback branches for GitHub links:" )
252+ print (' Fast-DDS: "{}"' .format (fastdds_fallback_branch ))
253+ print (' Fast-DDS-docs: "{}"' .format (fastdds_docs_fallback_branch ))
254+ print (' Fast-DDS-Python: "{}"' .format (fastdds_python_fallback_branch ))
255+ print (' Fast-DDS-Gen: "{}"' .format (fastdds_gen_fallback_branch ))
256+
172257# Check if we're running on Read the Docs' servers
173258read_the_docs_build = os .environ .get ('READTHEDOCS' , None ) == 'True'
174259if read_the_docs_build :
@@ -208,21 +293,17 @@ def configure_doxyfile(
208293 fastdds_repo_name ,
209294 )
210295
211- # Documentation repository branch
212- docs_branch = get_git_branch ()
213- print ('Current documentation branch is "{}"' .format (docs_branch ))
214-
215- # User specified Fast DDS branch
216- fastdds_branch = os .environ .get ('FASTDDS_BRANCH' , None )
217-
218- # First try to checkout to ${FASTDDS_BRANCH}
219- # Else checkout to 2.14.x
220- if (fastdds_branch and
221- fastdds .refs .__contains__ ('origin/{}' .format (fastdds_branch ))):
222- fastdds_branch = 'origin/{}' .format (fastdds_branch )
296+ # Verify the desired branch actually exists in the cloned remote, falling back to 2.14.x if not.
297+ fastdds_branch = fastdds_fallback_branch
298+ if fastdds .refs .__contains__ ("origin/{}" .format (fastdds_branch )):
299+ fastdds_branch = "origin/{}" .format (fastdds_branch )
223300 else :
224- fastdds_branch = 'origin/2.14.x'
225- print (f'Fast DDS branch is not set by env var. Using "{ fastdds_branch } "' )
301+ print (
302+ 'Fast DDS does not have branch "{}"; falling back to 2.14.x' .format (
303+ fastdds_branch
304+ )
305+ )
306+ fastdds_branch = "origin/2.14.x"
226307
227308 # Actual checkout
228309 print ('Checking out Fast DDS branch "{}"' .format (fastdds_branch ))
@@ -235,18 +316,17 @@ def configure_doxyfile(
235316 fastdds_python_repo_name ,
236317 )
237318
238- # User specified Fast DDS branch
239- fastdds_python_branch = os .environ .get ('FASTDDS_PYTHON_BRANCH' , None )
240-
241- # First try to checkout to ${FASTDDS_PYTHON_BRANCH}
242- # Else checkout to 1.4.x
243- if (fastdds_python_branch and
244- fastdds_python .refs .__contains__ (
245- 'origin/{}' .format (fastdds_python_branch ))):
246- fastdds_python_branch = 'origin/{}' .format (fastdds_python_branch )
319+ # Verify the desired branch actually exists in the cloned remote, falling back to 2.14.x if not.
320+ fastdds_python_branch = fastdds_python_fallback_branch
321+ if fastdds_python .refs .__contains__ ("origin/{}" .format (fastdds_python_branch )):
322+ fastdds_python_branch = "origin/{}" .format (fastdds_python_branch )
247323 else :
248- fastdds_python_branch = 'origin/1.4.x'
249- print (f'Fast DDS Python branch is not set by env var. Using "{ fastdds_python_branch } "' )
324+ print (
325+ 'Fast DDS Python does not have branch "{}"; falling back to 2.14.x' .format (
326+ fastdds_python_branch
327+ )
328+ )
329+ fastdds_python_branch = "origin/2.14.x"
250330
251331 # Actual checkout
252332 print ('Checking out Fast DDS Python branch "{}"' .format (
@@ -315,12 +395,40 @@ def configure_doxyfile(
315395# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
316396# ones.
317397extensions = [
318- 'breathe' ,
319- 'sphinxcontrib.plantuml' ,
320- 'sphinx.ext.autodoc' , # Document Pydoc documentation from Python bindings.
321- 'sphinx_tabs.tabs'
398+ "breathe" ,
399+ "sphinx_copybutton" ,
400+ "sphinx_design" ,
401+ "sphinx_substitution_extensions" ,
402+ "sphinx_tabs.tabs" ,
403+ "sphinx_toolbox.collapse" ,
404+ "sphinx.ext.autodoc" , # Document Pydoc documentation from Python bindings.
405+ "sphinx.ext.extlinks" ,
406+ "sphinxcontrib.plantuml" ,
322407]
323408
409+ extlinks = {
410+ # Fast-DDS repo (tree = directory, blob = file)
411+ "fastdds-tree" : (
412+ f"https://github.com/eProsima/Fast-DDS/tree/{ fastdds_fallback_branch } /%s" , "%s"
413+ ),
414+ "fastdds-blob" : (
415+ f"https://github.com/eProsima/Fast-DDS/blob/{ fastdds_fallback_branch } /%s" , "%s"
416+ ),
417+ # Fast-DDS-python repo
418+ "fastdds-python-tree" : (
419+ f"https://github.com/eProsima/Fast-DDS-Python/tree/{ fastdds_python_fallback_branch } /%s" , "%s"
420+ ),
421+ # Fast-DDS-docs repo (code examples embedded in the docs repo)
422+ "fastdds-docs-tree" : (
423+ f"https://github.com/eProsima/Fast-DDS-docs/tree/{ fastdds_docs_fallback_branch } /%s" , "%s"
424+ ),
425+ # Fast-DDS-Gen raw files
426+ "fastddsgen-raw" : (
427+ f"https://raw.githubusercontent.com/eProsima/Fast-DDS-Gen/{ fastdds_gen_fallback_branch } /%s" ,
428+ "%s" ,
429+ ),
430+ }
431+
324432sphinx_tabs_disable_css_loading = False
325433sphinx_tabs_disable_tab_closing = True
326434
@@ -462,7 +570,12 @@ def configure_doxyfile(
462570# further. For a list of options available for each theme, see the
463571# documentation.
464572#
465- # html_theme_options = {}
573+ html_theme_options = {}
574+ html_theme_options .update (download_json ())
575+
576+ html_use_smartypants = True
577+
578+ html_css_files = [select_css (script_path )]
466579
467580# Add any paths that contain custom themes here, relative to this directory.
468581# html_theme_path = []
0 commit comments