relnotes: Rework treatment of included package list
authorBen Gamari <bgamari.foss@gmail.com>
Mon, 27 Nov 2017 19:01:02 +0000 (14:01 -0500)
committerBen Gamari <ben@smart-cactus.org>
Tue, 28 Nov 2017 01:28:37 +0000 (20:28 -0500)
Previously the included package lists took a disproportionate amount of
space in the resulting document and were difficult to maintain. Turn it
into a table.

Subscribers: rwbarton, thomie

Differential Revision: https://phabricator.haskell.org/D4230

docs/users_guide/8.4.1-notes.rst
docs/users_guide/conf.py
docs/users_guide/flags.py
docs/users_guide/ghc_packages.py [new file with mode: 0644]
docs/users_guide/utils.py [new file with mode: 0644]

index 1acab73..09c4a6d 100644 (file)
@@ -373,9 +373,48 @@ Build system
   to notify ``base`` that the ``rts`` has been split, or vice versa.
   (see :ghc-ticket:`5987`).
 
+
+Included libraries
+------------------
+
+The package database provided with this distribution also contains a number of
+packages other than GHC itself. See the changelogs provided with these packages
+for further change information.
+
+.. ghc-package-list::
+
+    libraries/array/array.cabal:             Dependency of ``ghc`` library
+    libraries/base/base.cabal:               Core library
+    libraries/binary/binary.cabal:           Dependency of ``ghc`` library
+    libraries/bytestring/bytestring.cabal:   Deppendency of ``ghc`` library
+    libraries/Cabal/Cabal/Cabal.cabal:       Dependency of ``ghc-pkg`` utility
+    libraries/containers/containers.cabal:   Dependency of ``ghc`` library
+    libraries/deepseq/deepseq.cabal:         Dependency of ``ghc`` library
+    libraries/directory/directory.cabal:     Dependency of ``ghc`` library
+    libraries/filepath/filepath.cabal:       Dependency of ``ghc`` library
+    compiler/ghc.cabal:                      The compiler itself
+    libraries/ghci/ghci.cabal:               The REPL interface
+    libraries/ghc-boot/ghc-boot.cabal:       Internal compiler library
+    libraries/ghc-compact/ghc-compact.cabal: Core library
+    libraries/ghc-prim/ghc-prim.cabal:       Core library
+    libraries/haskeline/haskeline.cabal:     Dependency of ``ghci`` executable
+    libraries/hpc/hpc.cabal:                 Dependency of ``hpc`` executable
+    libraries/integer-gmp/integer-gmp.cabal: Core library
+    libraries/mtl/mtl.cabal:                 Dependency of ``Cabal`` library
+    libraries/parsec/parsec.cabal:           Dependency of ``Cabal`` library
+    libraries/process/process.cabal:         Dependency of ``ghc`` library
+    libraries/template-haskell/template-haskell.cabal:     Core library
+    libraries/text/text.cabal:               Dependency of ``Cabal`` library
+    libraries/time/time.cabal:               Dependency of ``ghc`` library
+    libraries/transformers/transformers.cabal: Dependency of ``ghc`` library
+    libraries/unix/unix.cabal:               Dependency of ``ghc`` library
+    libraries/Win32/Win32.cabal:             Dependency of ``ghc`` library
+    libraries/xhtml/xhtml.cabal:             Dependency of ``haddock`` executable
+
 Win32
 ~~~~~
 
--  Version number 2.6.x.x (was 2.5.4.1)
-   NOTE: This release is a backwards incompatible release which corrects the type of certain APIs.
-   See issue https://github.com/haskell/win32/issues/24.
+.. attention::
+
+    This release is a backwards incompatible release which corrects the type of
+    certain APIs. See issue `#24 <https://github.com/haskell/win32/issues/24>`_.
index 41b446a..4d4704a 100644 (file)
@@ -13,7 +13,11 @@ sys.path.insert(0, os.path.abspath('.'))
 from ghc_config import extlinks, version
 import ghc_config
 
-extensions = ['sphinx.ext.extlinks', 'sphinx.ext.mathjax', 'flags']
+extensions = ['sphinx.ext.extlinks',
+              'sphinx.ext.mathjax',
+              # GHC-specific extensions
+              'flags',
+              'ghc_packages']
 
 templates_path = ['.templates']
 source_suffix = '.rst'
index 66b0e92..cc30b8c 100644 (file)
@@ -49,6 +49,7 @@ from docutils.parsers.rst import Directive, directives
 from sphinx import addnodes
 from sphinx.domains.std import GenericObject
 from sphinx.errors import SphinxError
+from utils import build_table_from_list
 
 ### Settings
 
@@ -326,31 +327,6 @@ class LanguageExtension(GenericFlag):
 
 ### Flag Printing
 
-# Taken from Docutils source inside the ListTable class. We must bypass
-# using the class itself, but this function comes in handy.
-def build_table_from_list(table_data, col_widths):
-    table = nodes.table()
-    tgroup = nodes.tgroup(cols=len(col_widths))
-    table += tgroup
-    for col_width in col_widths:
-        colspec = nodes.colspec(colwidth=col_width)
-        tgroup += colspec
-    rows = []
-    for row in table_data:
-        row_node = nodes.row()
-        for cell in row:
-            entry = nodes.entry()
-            entry += cell
-            row_node += entry
-        rows.append(row_node)
-    thead = nodes.thead()
-    thead.extend(rows[:1])
-    tgroup += thead
-    tbody = nodes.tbody()
-    tbody.extend(rows[1:])
-    tgroup += tbody
-    return table
-
 
 # Generate a table of flags
 def generate_flag_table(flags, category):
diff --git a/docs/users_guide/ghc_packages.py b/docs/users_guide/ghc_packages.py
new file mode 100644 (file)
index 0000000..c91a7f2
--- /dev/null
@@ -0,0 +1,64 @@
+from docutils import nodes
+from docutils.parsers.rst import Directive, directives
+from sphinx import addnodes
+from sphinx.domains.std import GenericObject
+from sphinx.errors import SphinxError
+from utils import build_table_from_list
+
+def read_cabal_file(pkg_path):
+    import re
+    cabal_file = open(pkg_path, 'r').read()
+    pkg_name = re.search(r'[nN]ame:\s*([-a-zA-Z0-9]+)', cabal_file)
+    if pkg_name is not None:
+        pkg_name = pkg_name.group(1)
+    else:
+        raise RuntimeError("Failed to parse `Name:` field from %s" % pkg_path)
+
+    pkg_version = re.search(r'[vV]ersion:\s*(\d+(\.\d+)*)', cabal_file)
+    if pkg_version is not None:
+        pkg_version = pkg_version.group(1)
+    else:
+        raise RuntimeError("Failed to parse `Version:` field from %s" % pkg_path)
+
+    return (pkg_name, pkg_version)
+
+
+class PackageListDirective(Directive):
+    has_content = True
+    def run(self):
+        self.assert_has_content()
+
+        packages = []
+        for line in self.content:
+            (pkg_path, _, reason) = line.partition(':')
+            if len(reason) == 0:
+                raise RuntimeError("Missing reason for inclusion of package %s"
+                                   % pkg_path)
+
+            # Parse reason
+            from docutils.statemachine import ViewList
+            reason_vl = ViewList(initlist=[reason.strip()])
+            reason_node = nodes.paragraph()
+            self.state.nested_parse(reason_vl, 0, reason_node)
+            packages.append((pkg_path, reason_node))
+
+        # Create column headers for table
+        header = [ nodes.inline(text=h)
+                   for h in ["Package", "Version", "Reason for inclusion"] ]
+        package_list = [header]
+
+        for (pkg_path, reason) in sorted(packages):
+            (pkg_name, pkg_version) = read_cabal_file(pkg_path)
+            cells = [ nodes.inline(text=pkg_name),
+                      nodes.inline(text=pkg_version),
+                      reason ]
+            package_list.append(cells)
+
+        table = build_table_from_list(package_list, [20, 20, 40])
+        return [table]
+
+### Initialization
+def setup(app):
+    app.add_directive('ghc-package-list', PackageListDirective)
+
+    return {'version': '1.0'}
diff --git a/docs/users_guide/utils.py b/docs/users_guide/utils.py
new file mode 100644 (file)
index 0000000..128ae51
--- /dev/null
@@ -0,0 +1,26 @@
+from docutils import nodes
+
+# Taken from Docutils source inside the ListTable class. We must bypass
+# using the class itself, but this function comes in handy.
+def build_table_from_list(table_data, col_widths):
+    table = nodes.table()
+    tgroup = nodes.tgroup(cols=len(col_widths))
+    table += tgroup
+    for col_width in col_widths:
+        colspec = nodes.colspec(colwidth=col_width)
+        tgroup += colspec
+    rows = []
+    for row in table_data:
+        row_node = nodes.row()
+        for cell in row:
+            entry = nodes.entry()
+            entry += cell
+            row_node += entry
+        rows.append(row_node)
+    thead = nodes.thead()
+    thead.extend(rows[:1])
+    tgroup += thead
+    tbody = nodes.tbody()
+    tbody.extend(rows[1:])
+    tgroup += tbody
+    return table