Repository: mesonbuild/meson

Issue:
hotdoc module generates broken "Edit on github" links
- Browse to https://mesonbuild.com/Hotdoc-module.html
- Click "Edit on github"
- Be redirected to https://github.com/mesonbuild/meson//edit/master/docs/builddir/markdown/Hotdoc-module.md
- notice "builddir/" in the url

/cc @thiblahute 

Discussion:
eli-schwartz: Fixed unittests to expect the new layout...
eli-schwartz: Test failures are not relevant --  unittests-appleclang has clock skew, cygwin is known to be misbehaving.
MathieuDuponchelle: lgtm
TheQwertiest: Copy pasted comment: 
@eli-schwartz , can't say I agree with your changes: it now edits the file in-tree and not out-of-tree, which is not a mesonic way (and dirties the source tree).
eli-schwartz: I suggest you reread the PR!

Hotdoc processes an in-tree .md template, an out of tree include path, and generates an out of tree html file.
TheQwertiest: > I suggest you reread the PR!

My bad, I've misread `cur_bdir` as current source dir.
eli-schwartz: The commit diff for the gen_docs target hasn't really changed, --output-directory just had its join_paths and second component removed due to its un-mesonic use of a subdirectory for emitting outputs.
eli-schwartz: Rebased on master in order to grab CI improvements, because why not.

Patch:
diff --git a/docs/markdown_dynamic/Commands.md b/docs/markdown/Commands.md
similarity index 82%
rename from docs/markdown_dynamic/Commands.md
rename to docs/markdown/Commands.md
index a35b4da96..46bd21b87 100644
--- a/docs/markdown_dynamic/Commands.md
+++ b/docs/markdown/Commands.md
@@ -16,15 +16,11 @@ For the full list of all available options for a specific command use the follow
 
 ### configure
 
-```
-{{ cmd_help['configure']['usage'] }}
-```
+{{ configure_usage.inc }}
 
 Changes options of a configured meson project.
 
-```
-{{ cmd_help['configure']['arguments'] }}
-```
+{{ configure_arguments.inc }}
 
 Most arguments are the same as in [`setup`](#setup).
 
@@ -46,15 +42,11 @@ meson configure builddir -Doption=new_value
 
 *(since 0.54.0)*
 
-```
-{{ cmd_help['compile']['usage'] }}
-```
+{{ compile_usage.inc }}
 
 Builds a default or a specified target of a configured meson project.
 
-```
-{{ cmd_help['compile']['arguments'] }}
-```
+{{ compile_arguments.inc }}
 
 `--verbose` argument is available since 0.55.0.
 
@@ -115,15 +107,11 @@ meson compile coverage-html
 
 *(since 0.52.0)*
 
-```
-{{ cmd_help['dist']['usage'] }}
-```
+{{ dist_usage.inc }}
 
 Generates a release archive from the current source tree.
 
-```
-{{ cmd_help['dist']['arguments'] }}
-```
+{{ dist_arguments.inc }}
 
 See [notes about creating releases](Creating-releases.md) for more info.
 
@@ -138,15 +126,11 @@ meson dist -C builddir
 
 *(since 0.45.0)*
 
-```
-{{ cmd_help['init']['usage'] }}
-```
+{{ init_usage.inc }}
 
 Creates a basic set of build files based on a template.
 
-```
-{{ cmd_help['init']['arguments'] }}
-```
+{{ init_arguments.inc }}
 
 #### Examples:
 
@@ -157,15 +141,11 @@ meson init -C sourcedir
 
 ### introspect
 
-```
-{{ cmd_help['introspect']['usage'] }}
-```
+{{ introspect_usage.inc }}
 
 Displays information about a configured meson project.
 
-```
-{{ cmd_help['introspect']['arguments'] }}
-```
+{{ introspect_arguments.inc }}
 
 #### Examples:
 
@@ -178,15 +158,11 @@ meson introspect builddir
 
 *(since 0.47.0)*
 
-```
-{{ cmd_help['install']['usage'] }}
-```
+{{ install_usage.inc }}
 
 Installs the project to the prefix specified in [`setup`](#setup).
 
-```
-{{ cmd_help['install']['arguments'] }}
-```
+{{ install_arguments.inc }}
 
 See [the installation documentation](Installing.md) for more info.
 
@@ -206,31 +182,23 @@ DESTDIR=/path/to/staging/area meson install -C builddir
 
 *(since 0.50.0)*
 
-```
-{{ cmd_help['rewrite']['usage'] }}
-```
+{{ rewrite_usage.inc }}
 
 Modifies the meson project.
 
-```
-{{ cmd_help['rewrite']['arguments'] }}
-```
+{{ rewrite_arguments.inc }}
 
 See [the meson file rewriter documentation](Rewriter.md) for more info.
 
 ### setup
 
-```
-{{ cmd_help['setup']['usage'] }}
-```
+{{ setup_usage.inc }}
 
 Configures a build directory for the meson project.
 
 This is the default meson command (invoked if there was no COMMAND supplied).
 
-```
-{{ cmd_help['setup']['arguments'] }}
-```
+{{ setup_arguments.inc }}
 
 See [meson introduction page](Running-Meson.md#configuring-the-build-directory) for more info.
 
@@ -245,27 +213,19 @@ meson setup builddir
 
 *(since 0.49.0)*
 
-```
-{{ cmd_help['subprojects']['usage'] }}
-```
+{{ subprojects_usage.inc }}
 
 Manages subprojects of the meson project.
 
-```
-{{ cmd_help['subprojects']['arguments'] }}
-```
+{{ subprojects_arguments.inc }}
 
 ### test
 
-```
-{{ cmd_help['test']['usage'] }}
-```
+{{ test_usage.inc }}
 
 Run tests for the configure meson project.
 
-```
-{{ cmd_help['test']['arguments'] }}
-```
+{{ test_arguments.inc }}
 
 See [the unit test documentation](Unit-tests.md) for more info.
 
@@ -283,14 +243,10 @@ meson test -C builddir specific_test_1 specific_test_2
 
 ### wrap
 
-```
-{{ cmd_help['wrap']['usage'] }}
-```
+{{ wrap_usage.inc }}
 
 An utility to manage WrapDB dependencies.
 
-```
-{{ cmd_help['wrap']['arguments'] }}
-```
+{{ wrap_arguments.inc }}
 
 See [the WrapDB tool documentation](Using-wraptool.md) for more info.
diff --git a/docs/meson.build b/docs/meson.build
index 496588d40..fa80512e7 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -2,22 +2,14 @@ project('Meson documentation', version: '1.0')
 
 cur_bdir = meson.current_build_dir()
 
-# Copy all files to build dir, since HotDoc uses relative paths
-run_command(
-    files('../tools/copy_files.py'),
-    '-C', meson.current_source_dir(),
-    '--output-dir', cur_bdir,
-    'markdown', 'theme', 'sitemap.txt', 
-    check: true)
-
 # Only the script knows which files are being generated
 docs_gen = custom_target(
     'gen_docs',
     input: files('markdown/index.md'),
-    output: 'gen_docs.dummy',
+    output: 'gen_docs.stamp',
     command: [
         files('../tools/regenerate_docs.py'),
-        '--output-dir', join_paths(cur_bdir, 'markdown'),
+        '--output-dir', cur_bdir,
         '--dummy-output-file', '@OUTPUT@',
     ],
     build_by_default: true,
@@ -26,15 +18,15 @@ docs_gen = custom_target(
 hotdoc = import('hotdoc')
 documentation = hotdoc.generate_doc(meson.project_name(),
     project_version: meson.project_version(),
-    sitemap: join_paths(cur_bdir, 'sitemap.txt'),
+    sitemap: 'sitemap.txt',
     build_by_default: true,
     depends: docs_gen,
-    index: join_paths(cur_bdir, 'markdown/index.md'),
+    index: 'markdown/index.md',
     install: false,
     extra_assets: ['images/'],
-    include_paths: [join_paths(cur_bdir, 'markdown')],
+    include_paths: ['markdown', cur_bdir],
     default_license: 'CC-BY-SAv4.0',
-    html_extra_theme: join_paths(cur_bdir, 'theme', 'extra'),
+    html_extra_theme: join_paths('theme', 'extra'),
     git_upload_repository: 'git@github.com:jpakkane/jpakkane.github.io.git',
     edit_on_github_repository: 'https://github.com/mesonbuild/meson',
     syntax_highlighting_activate: true,
diff --git a/tools/regenerate_docs.py b/tools/regenerate_docs.py
index 74a8b0c0c..b9b994a1a 100755
--- a/tools/regenerate_docs.py
+++ b/tools/regenerate_docs.py
@@ -20,7 +20,6 @@ Regenerate markdown docs by using `meson.py` from the root dir
 '''
 
 import argparse
-import jinja2
 import os
 import re
 import subprocess
@@ -108,20 +107,13 @@ def get_commands_data(root_dir: Path) -> T.Dict[str, T.Any]:
 
     return cmd_data
 
-def regenerate_commands(root_dir: Path, output_dir: Path) -> None:
-    with open(root_dir/'docs'/'markdown_dynamic'/'Commands.md') as f:
-        template = f.read()
-
+def generate_hotdoc_includes(root_dir: Path, output_dir: Path) -> None:
     cmd_data = get_commands_data(root_dir)
 
-    t = jinja2.Template(template, undefined=jinja2.StrictUndefined, keep_trailing_newline=True)
-    content = t.render(cmd_help=cmd_data)
-
-    output_file = output_dir/'Commands.md'
-    with open(output_file, 'w') as f:
-        f.write(content)
-
-    print(f'`{output_file}` was regenerated')
+    for cmd, parsed in cmd_data.items():
+        for typ in parsed.keys():
+            with open(output_dir / (cmd+'_'+typ+'.inc'), 'w') as f:
+                f.write(parsed[typ])
 
 def regenerate_docs(output_dir: PathLike,
                     dummy_output_file: T.Optional[PathLike]) -> None:
@@ -133,7 +125,7 @@ def regenerate_docs(output_dir: PathLike,
 
     root_dir = Path(__file__).resolve().parent.parent
 
-    regenerate_commands(root_dir, output_dir)
+    generate_hotdoc_includes(root_dir, output_dir)
 
     if dummy_output_file:
         with open(output_dir/dummy_output_file, 'w') as f:


Test patch:
diff --git a/run_unittests.py b/run_unittests.py
index 1ff54eb37..d6afaff2e 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -4915,7 +4915,7 @@ class AllPlatformTests(BasePlatformTests):
         # The docs directory is not in release tarballs.
         if not os.path.isdir('docs'):
             raise unittest.SkipTest('Doc directory does not exist.')
-        doc_path = 'docs/markdown_dynamic/Commands.md'
+        doc_path = 'docs/markdown/Commands.md'
 
         md = None
         with open(doc_path, encoding='utf-8') as f:
@@ -4944,13 +4944,9 @@ class AllPlatformTests(BasePlatformTests):
 
         def get_data_pattern(command):
             return re.compile(
-                r'^```[\r\n]'
-                r'{{ cmd_help\[\'' + command + r'\'\]\[\'usage\'\] }}[\r\n]'
-                r'^```[\r\n]'
+                r'{{ ' + command + r'_usage.inc }}[\r\n]'
                 r'.*?'
-                r'^```[\r\n]'
-                r'{{ cmd_help\[\'' + command + r'\'\]\[\'arguments\'\] }}[\r\n]'
-                r'^```',
+                r'{{ ' + command + r'_arguments.inc }}[\r\n]',
                 flags = re.MULTILINE|re.DOTALL)
 
         for command in md_commands:
@@ -7533,7 +7529,7 @@ class LinuxCrossArmTests(BaseLinuxCrossTests):
             '-Dbuild.pkg_config_path=' + os.path.join(testdir, 'build_extra_path'),
             '-Dpkg_config_path=' + os.path.join(testdir, 'host_extra_path'),
         ])
-    
+
     def test_run_native_test(self):
         '''
         https://github.com/mesonbuild/meson/issues/7997