summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbderrahim Kitouni <abderrahim.kitouni@codethink.co.uk>2023-10-03 21:00:19 +0200
committerLuca Boccassi <luca.boccassi@gmail.com>2023-10-09 12:16:20 +0200
commit3c1f396f694069a71699ecc9a53806d531a25748 (patch)
treec7c3d2a69c553b8a763883551dd2aadafbbec554
parentMerge pull request #29495 from yuwata/network-manager-state-file (diff)
downloadsystemd-3c1f396f694069a71699ecc9a53806d531a25748.tar.xz
systemd-3c1f396f694069a71699ecc9a53806d531a25748.zip
man: support multiple versions of the documentation on the website
This changes the doc-sync meson target from a simple rsync command to a script that: * puts the documentation in a subdirectory according to the version * injects a bit of javascript to add a drop-down to switch between versions * updates an index.json file with the newly uploaded version * keeps the latest/ directory up to date with the latest version * supports a --no-latest switch to be used when uploading older versions
-rw-r--r--man/meson.build9
-rw-r--r--meson.build1
-rwxr-xr-xtools/sync-docs.py134
3 files changed, 138 insertions, 6 deletions
diff --git a/man/meson.build b/man/meson.build
index e6798b7d4e..e4f2905d60 100644
--- a/man/meson.build
+++ b/man/meson.build
@@ -190,12 +190,9 @@ if rsync.found()
run_target(
'doc-sync',
depends : man_pages + html_pages,
- command : [rsync, '-rlv',
- '--delete-excluded',
- '--include=man',
- '--include=*.html',
- '--exclude=*',
- '--omit-dir-times',
+ command : [sync_docs_py,
+ '--version',
+ '@0@'.format(meson.project_version()),
meson.current_build_dir(),
get_option('www-target')])
endif
diff --git a/meson.build b/meson.build
index 5e9ca285ac..b01dd9cd73 100644
--- a/meson.build
+++ b/meson.build
@@ -1795,6 +1795,7 @@ export_dbus_interfaces_py = find_program('tools/dbus_exporter.py')
generate_gperfs = find_program('tools/generate-gperfs.py')
make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py')
make_directive_index_py = find_program('tools/make-directive-index.py')
+sync_docs_py = find_program('tools/sync-docs.py')
make_man_index_py = find_program('tools/make-man-index.py')
meson_render_jinja2 = find_program('tools/meson-render-jinja2.py')
update_dbus_docs_py = find_program('tools/update-dbus-docs.py')
diff --git a/tools/sync-docs.py b/tools/sync-docs.py
new file mode 100755
index 0000000000..bab99f8cb3
--- /dev/null
+++ b/tools/sync-docs.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+from argparse import ArgumentParser
+import glob
+import json
+import os
+import re
+import subprocess
+import sys
+
+import requests
+
+BASE_URL = "https://www.freedesktop.org/software/systemd/man/"
+JQUERY_URL = "https://code.jquery.com/jquery-3.7.1.min.js"
+SCRIPT_TAG = '<script src="{}"></script>'
+
+NAV_JS = """
+$(document).ready(function() {
+ $.getJSON("../index.json", function(data) {
+ data.sort().reverse();
+
+ var [filename, dirname] = window.location.pathname.split("/").reverse();
+
+ var items = [];
+ $.each( data, function(_, version) {
+ if (version == dirname) {
+ items.push( "<option selected value='" + version + "'>" + "systemd " + version + "</option>");
+ } else if (dirname == "latest" && version == data[0]) {
+ items.push( "<option selected value='" + version + "'>" + "systemd " + version + "</option>");
+ } else {
+ items.push( "<option value='" + version + "'>" + "systemd " + version + "</option>");
+ }
+ });
+
+ $("span:first").html($( "<select/>", {
+ id: "version-selector",
+ html: items.join( "" )
+ }));
+
+ $("#version-selector").on("change", function() {
+ window.location.assign("../" + $(this).val() + "/" + filename);
+ });
+ });
+});
+"""
+
+
+def process_file(filename):
+ with open(filename) as f:
+ contents = f.read()
+
+ if SCRIPT_TAG.format("../nav.js") in contents:
+ return
+
+ body_tag = re.search("<body[^>]*>", contents)
+ new_contents = (
+ contents[: body_tag.end()]
+ + SCRIPT_TAG.format(JQUERY_URL)
+ + SCRIPT_TAG.format("../nav.js")
+ + contents[body_tag.end() :]
+ )
+
+ with open(filename, "w") as f:
+ f.write(new_contents)
+
+
+def update_index_file(version, index_filename):
+ response = requests.get(BASE_URL + "index.json")
+ if response.status_code == 404:
+ index = []
+ elif response.ok:
+ index = response.json()
+ else:
+ sys.exit(f"Error getting index: {response.status_code} {response.reason}")
+
+ if version not in index:
+ index.insert(0, version)
+
+ with open(index_filename, "w") as f:
+ json.dump(index, f)
+
+
+def main(version, directory, www_target, latest):
+ index_filename = os.path.join(directory, "index.json")
+ nav_filename = os.path.join(directory, "nav.js")
+
+ for filename in glob.glob(os.path.join(directory, "*.html")):
+ process_file(filename)
+
+ with open(nav_filename, "w") as f:
+ f.write(NAV_JS)
+
+ update_index_file(version, index_filename)
+
+ dirs = [version]
+
+ if latest:
+ dirs.append("latest")
+
+ for d in dirs:
+ subprocess.check_call(
+ [
+ "rsync",
+ "-rlv",
+ "--delete-excluded",
+ "--include=*.html",
+ "--exclude=*",
+ "--omit-dir-times",
+ directory + "/", # copy contents of directory
+ os.path.join(www_target, d),
+ ]
+ )
+
+ subprocess.check_call(
+ [
+ "rsync",
+ "-v",
+ os.path.join(directory, "index.json"),
+ os.path.join(directory, "nav.js"),
+ www_target,
+ ]
+ )
+
+
+if __name__ == "__main__":
+ parser = ArgumentParser()
+ parser.add_argument("--version", required=True)
+ parser.add_argument("--no-latest", dest="latest", action="store_false")
+ parser.add_argument("directory")
+ parser.add_argument("www_target")
+
+ args = parser.parse_args()
+ main(args.version, args.directory, args.www_target, args.latest)