diff --git a/docs/user/Makefile b/docs/user/Makefile index b471bbd3331d9f544bdb228fc5d489fb0c964ca3..a0c54493fa398d751237993ac5f71c4cbe384a61 100644 --- a/docs/user/Makefile +++ b/docs/user/Makefile @@ -10,13 +10,16 @@ BUILDDIR = _build all: html -software-origins/dynamic/table.inc: ../software-origins-support.yml ../../swh/docs/generate_software_origins_list.py ../../swh/docs/generate_software_origin_status.py - python3 -m swh.docs.generate_software_origins_list ../software-origins-support.yml software-origins/dynamic/table.inc - # technically the following should be in its own target, but it would be - # overly complicated. +software-origins/dynamic/table.inc: ../software-origins-support.yml ../../swh/docs/generate_software_origins_list.py ../../swh/docs/generate_software_origin_status.py ../../swh/docs/software_origins.py python3 -m swh.docs.generate_software_origin_status ../software-origins-support.yml software-origins/dynamic/ + # technically the above should be in their own targets, but it would be + # overly complicated. + python3 -m swh.docs.generate_software_origins_list ../software-origins-support.yml software-origins/dynamic/table.inc + +software-origins/dynamic/lister_table.inc software-origins/dynamic/loader_table.inc: ../software-origins-support.yml ../../swh/docs/generate_lister_loader_lists.py ../../swh/docs/software_origins.py + python3 -m swh.docs.generate_lister_loader_lists ../software-origins-support.yml software-origins/dynamic/lister_table.inc software-origins/dynamic/loader_table.inc -dynamic-rst: software-origins/dynamic/table.inc +dynamic-rst: software-origins/dynamic/table.inc software-origins/dynamic/lister_table.inc software-origins/dynamic/loader_table.inc # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). diff --git a/docs/user/index.rst b/docs/user/index.rst index ba41511fd5780d4afec2f64f9ff6bf47d3041d2f..2922eec8037007902cf0c92e173a83856646fe38 100644 --- a/docs/user/index.rst +++ b/docs/user/index.rst @@ -8,6 +8,8 @@ Usage faq/index software-origins/index + listers + loaders save_code_now/webhooks/index using_data/index diff --git a/docs/user/listers.rst b/docs/user/listers.rst new file mode 100644 index 0000000000000000000000000000000000000000..e601e8523823811494ea22b41a70fde833f78aae --- /dev/null +++ b/docs/user/listers.rst @@ -0,0 +1,16 @@ +.. _user-listers: + +Software Heritage listers +************************* + +A :term:`lister` is a software component used for the discovering of software origins to +load into the |swh| archive. + +Only forges and package managers with listers are enumerated below; see also the +:ref:`user-software-origins` for a list including loaders (eg. for version control +systems). + + +This page references all available listers and links to their high-level documentation. + +.. include:: software-origins/dynamic/lister_table.inc diff --git a/docs/user/loaders.rst b/docs/user/loaders.rst new file mode 100644 index 0000000000000000000000000000000000000000..083a8eb0a50b31993650a351ab60e9c981f6e5f8 --- /dev/null +++ b/docs/user/loaders.rst @@ -0,0 +1,15 @@ +.. _user-loaders: + +Software Heritage loaders +************************* + +A :term:`loader` is a software component used to ingest content into the |swh| archive. + +Only version control systems and package managers with their own loader are enumerated +below; see also the :ref:`user-software-origins` for a list including listers (eg. for +forges and package managers aggregating external packages). + + +This page references all available loaders and links to their high-level documentation. + +.. include:: software-origins/dynamic/loader_table.inc diff --git a/swh/docs/generate_lister_loader_lists.py b/swh/docs/generate_lister_loader_lists.py new file mode 100644 index 0000000000000000000000000000000000000000..f5fac54365961244403471ef4b143e1c05b26fbb --- /dev/null +++ b/swh/docs/generate_lister_loader_lists.py @@ -0,0 +1,224 @@ +# Copyright (C) 2023 The Software Heritage developers +# See the AUTHORS file at the top-level directory of this distribution +# License: GNU General Public License version 3, or any later version +# See top-level LICENSE file for more information + +"""Reads docs/devel/forge-support.yml and generates ReST documents with tables +summarizing the status of loaders ands listers.""" + +from pathlib import Path +import sys +import textwrap + +import tabulate +from typing_extensions import Literal + +from .software_origins import parse + +LISTERS_PRELUDE = """ +.. This file was generated by swh/docs/generate_forge_list.py using {source_yml} + +.. rst-class:: swh-logos-table + +.. table:: + :align: center + +""" + + +LOADERS_PRELUDE = """ +.. This file was generated by swh/docs/generate_forge_list.py using {source_yml} + +.. rst-class:: swh-logos-table + +.. table:: + :align: center + +""" + + +def write_table(data, lister_or_loader: Literal["lister", "loader"], file) -> None: + links = [] + headers = ( + f"{lister_or_loader.capitalize()} name", + "Related links", + "Current status", + "Related `grants <https://www.softwareheritage.org/grants/>`_", + ) + table = [] + for (forge_id, forge) in sorted(data["forges"].items()): + package_name = forge[lister_or_loader].package_name + links.append( + ( + f"{forge_id}-source", + forge[lister_or_loader].source, + ) + ) + + logo_cell = f"|{forge_id}_logo|\n\n:ref:`user-software-origins-{forge_id}`" + + if forge_id in ("cran", "gnu"): + # FIXME: swh-web coverage should have them lowercased, like everything else + id_in_swh_web_coverage = forge_id.upper() + else: + id_in_swh_web_coverage = forge_id + + status = forge[lister_or_loader].status + if status == "N/A": + # No lister or loader for this forge, skipping + continue + elif status == "dev": + status_cell = "In development" + links_cell = ( + f"* `Source Code <{forge_id}-source_>`__\n" + f"* :mod:`Developer documentation <{package_name}>`" + ) + elif status == "staging": + status_cell = "In staging" + if lister_or_loader == "loader": + links.append( + ( + f"{forge_id}-origins", + "https://webapp.staging.swh.network/browse/search/" + f"?with_visit=true&with_content=true&visit_type={forge_id}", + ) + ) + + links_cell = ( + f"* `Source Code <{forge_id}-source_>`__\n" + f"* :mod:`Developer documentation <{package_name}>`\n" + f"* `Browse origins <{forge_id}-origins_>`__" + ) + else: + links.append( + ( + f"{forge_id}-coverage", + "https://webapp.staging.swh.network/coverage/" + f"?focus={id_in_swh_web_coverage}#{id_in_swh_web_coverage}", + ) + ) + links_cell = ( + f"* `Source Code <{forge_id}-source_>`__\n" + f"* :mod:`Developer documentation <{package_name}>`\n" + f"* `See coverage <{forge_id}-coverage_>`__" + ) + elif status == "prod": + status_cell = "In production" + if lister_or_loader == "loader": + links.append( + ( + f"{forge_id}-origins", + f"https://archive.softwareheritage.org/browse/search/" + f"?with_visit=true&with_content=true&visit_type={forge_id}", + ) + ) + links_cell = ( + f"* `Source Code <{forge_id}-source_>`__\n" + f"* :mod:`Developer documentation <{package_name}>`\n" + f"* `Browse origins <{forge_id}-origins_>`__" + ) + else: + links.append( + ( + f"{forge_id}-coverage", + f"https://archive.softwareheritage.org/coverage/" + f"?focus={id_in_swh_web_coverage}#{id_in_swh_web_coverage}", + ) + ) + links_cell = ( + f"* `Source Code <{forge_id}-source_>`__\n" + f"* :mod:`Developer documentation <{package_name}>`\n" + f"* `See coverage <{forge_id}-coverage_>`__" + ) + else: + assert False, f"Unexpected status {status!r} for {forge_id}" + issue = forge[lister_or_loader].get("issue") + if issue: + links_cell += f"\n* `Tracking issue <{forge[lister_or_loader].issue}>`__" + + notes = forge.get("notes") + if notes: + status_cell = f"{status_cell}\n\n{notes}" + + grant_id = forge.get("grant") + grant = data["grants"][grant_id] if grant_id else None + developer_id = forge.get("developer") + if grant: + assert developer_id, f"{forge_id} has grant but no developer" + developer = data["developers"][developer_id] + grant_cell = ( + f"|{grant_id}|_\n\n" + f"(awarded to `{developer.name} <{developer.url}>`__)" + ) + else: + assert not developer_id, f"{forge_id} has developer but no grant" + grant_cell = "" + + table.append((logo_cell, links_cell, status_cell, grant_cell)) + + file.write( + textwrap.indent( + tabulate.tabulate(table, headers=headers, tablefmt="grid"), + prefix=" ", + ) + + "\n\n" + ) + + for (link_name, link_url) in links: + file.write(f".. _{link_name}: {link_url}\n") + + file.write("\n") + + +def write_logos(data, lister_or_loader: Literal["lister", "loader"], file) -> None: + for (forge_id, forge) in sorted(data["forges"].items()): + if forge[lister_or_loader]["status"] != "N/A": + file.write( + f".. |{forge_id}_logo| image:: ../../logos/{forge_id}.png\n" + f" :width: 50%\n" + f" :target: software-origins/{forge_id}.html\n" + f" :alt: {forge.name} {lister_or_loader}\n" + f"\n" + ) + + +def write_grants(data, file) -> None: + for (grant_id, grant) in data["grants"].items(): + file.write( + f".. |{grant_id}| replace:: {grant.funder}\n" + f".. _{grant_id}: {grant.announcement}\n" + f"\n" + ) + + +def main(input_path: Path, lister_output_path: Path, loader_output_path: Path) -> None: + data = parse(input_path) + + with lister_output_path.open("wt") as listers_file, loader_output_path.open( + "wt" + ) as loaders_file: + listers_file.write(LISTERS_PRELUDE.format(source_yml=input_path)) + loaders_file.write(LOADERS_PRELUDE.format(source_yml=input_path)) + + write_table(data, "lister", listers_file) + write_table(data, "loader", loaders_file) + + write_logos(data, "lister", listers_file) + write_logos(data, "loader", loaders_file) + + write_grants(data, listers_file) + write_grants(data, loaders_file) + + +if __name__ == "__main__": + try: + (_, input_path, lister_output_path, loader_output_path) = sys.argv + except ValueError: + print( + f"Syntax: {sys.argv[0]} docs/devel/forge-support.yml " + f"docs/user/software-origins/dynamic/lister_table.inc " + f"docs/user/software-origins/dynamic/loader_table.inc", + sys.stderr, + ) + exit(1) + main(Path(input_path), Path(lister_output_path), Path(loader_output_path)) diff --git a/swh/docs/generate_software_origins_list.py b/swh/docs/generate_software_origins_list.py index 5c0737e0c60c20158c74dba0dd1f4b6abd24831d..e2e64307629f58af2e34b968d7bd40e60c18167c 100644 --- a/swh/docs/generate_software_origins_list.py +++ b/swh/docs/generate_software_origins_list.py @@ -181,7 +181,7 @@ if __name__ == "__main__": except ValueError: print( f"Syntax: {sys.argv[0]} docs/devel/forge-support.yml " - f"docs/user/software-origins/index.rst", + f"docs/user/software-origins/dynamic/table.inc", sys.stderr, ) exit(1)