]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
man: support multiple versions of the documentation on the website
authorAbderrahim Kitouni <abderrahim.kitouni@codethink.co.uk>
Tue, 3 Oct 2023 19:00:19 +0000 (20:00 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Mon, 9 Oct 2023 10:16:20 +0000 (11:16 +0100)
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

man/meson.build
meson.build
tools/sync-docs.py [new file with mode: 0755]

index e6798b7d4e0675eaf05d2315952ffaef0b9eb92c..e4f2905d602e410b9968e7397f9e87e2664dbc9b 100644 (file)
@@ -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
index 5e9ca285acd70517b8f4e25a500c3450132a8170..b01dd9cd73d320158561e3236cdefe69af902015 100644 (file)
@@ -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 (executable)
index 0000000..bab99f8
--- /dev/null
@@ -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)