[calm - Cygwin server-side packaging maintenance script] branch master, updated. 20181020-10-g911eecc

jturney-9JcytcrH/[email protected]
Newsgroups gmane.os.cygwin.cvs.apps
Message-ID <[email protected]>


https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/calm.git;h=911eeccf54754e433fd1c4e4cc45d203bd31d50a

commit 911eeccf54754e433fd1c4e4cc45d203bd31d50a
Author: Jon Turney <[email protected]>
Date:   Wed Nov 8 14:28:04 2017 +0000

    Generate a per-package summary HTML page

https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/calm.git;h=735b2920f386a308ec120412ebd3c26c3e4d8055

commit 735b2920f386a308ec120412ebd3c26c3e4d8055
Author: Jon Turney <[email protected]>
Date:   Fri May 24 12:30:36 2019 +0100

    Make orphanmaint a parameter of Maintainers.read


Diff:
---
 TODO                                               |    1 +
 calm/calm.py                                       |   10 +-
 calm/compare-arches                                |    2 +-
 calm/maintainers.py                                |   23 ++-
 calm/pkg2html.py                                   |  239 +++++++++++++++++---
 test/test_calm.py                                  |   10 +-
 test/testdata/htdocs.expected/packages.inc         |   26 ++
 test/testdata/htdocs.expected/summary/arc.html     |   34 +++
 .../htdocs.expected/summary/base-cygwin.html       |   29 +++
 test/testdata/htdocs.expected/summary/corrupt.html |   29 +++
 .../htdocs.expected/summary/cygwin-debuginfo.html  |   32 +++
 .../htdocs.expected/summary/cygwin-devel.html      |   30 +++
 test/testdata/htdocs.expected/summary/cygwin.html  |   34 +++
 .../testdata/htdocs.expected/summary/keychain.html |   40 ++++
 .../htdocs.expected/summary/libdns_sd-devel.html   |   31 +++
 .../htdocs.expected/summary/libdns_sd1.html        |   30 +++
 .../htdocs.expected/summary/mDNSResponder.html     |   32 +++
 test/testdata/htdocs.expected/summary/obs-a.html   |   29 +++
 test/testdata/htdocs.expected/summary/obs-b.html   |   29 +++
 test/testdata/htdocs.expected/summary/openssh.html |   31 +++
 .../summary/per-version-replacement-hint-only.html |   30 +++
 .../htdocs.expected/summary/per-version.html       |   32 +++
 .../htdocs.expected/summary/perl-Net-SMTP-SSL.html |   30 +++
 test/testdata/htdocs.expected/summary/rpm-doc.html |   30 +++
 .../htdocs.expected/summary/staleversion.html      |   39 ++++
 test/testdata/htdocs.expected/summary/test-c.html  |   31 +++
 test/testdata/htdocs.expected/summary/test-d.html  |   29 +++
 test/testdata/htdocs.expected/summary/test-e.html  |   30 +++
 .../htdocs.expected/summary/testpackage.html       |   29 +++
 test/testdata/htdocs.expected/x86/packages.inc     |   27 ---
 test/testdata/process_arch/htdocs.expected         |   40 +++-
 31 files changed, 988 insertions(+), 80 deletions(-)

diff --git a/TODO b/TODO
index a892159..9d1ddd1 100644
--- a/TODO
+++ b/TODO
@@ -9,3 +9,4 @@
 * something to expire old soversions
 * atomically update .ini/.sig (rename of containing directory, if we put release/ was somewhere else?)
 * report changes in override.hint like we used to for setup.hint
+* maintainers.py should only re-read cygwin-pkg-maint if it's changed
diff --git a/calm/calm.py b/calm/calm.py
index 36a865f..3b7ea79 100755
--- a/calm/calm.py
+++ b/calm/calm.py
@@ -129,7 +129,7 @@ def process_relarea(args):
 
 def process_uploads(args, state):
     # read maintainer list
-    mlist = maintainers.Maintainer.read(args)
+    mlist = maintainers.Maintainer.read(args, getattr(args, 'orphanmaint', None))
 
     # make the list of all packages
     all_packages = maintainers.Maintainer.all_packages(mlist)
@@ -373,11 +373,9 @@ def do_main(args, state):
 #
 
 def do_output(args, state):
-    # for each arch
-    for arch in common_constants.ARCHES:
-        # update packages listings
-        # XXX: perhaps we need a --[no]listing command line option to disable this from being run?
-        pkg2html.update_package_listings(args, state.packages[arch], arch)
+    # update packages listings
+    # XXX: perhaps we need a --[no]listing command line option to disable this from being run?
+    pkg2html.update_package_listings(args, state.packages)
 
     # for each arch
     for arch in common_constants.ARCHES:
diff --git a/calm/compare-arches b/calm/compare-arches
index feb31be..37e1861 100755
--- a/calm/compare-arches
+++ b/calm/compare-arches
@@ -91,7 +91,7 @@ def main(args):
         print("%s is only in arch %s" % (p, [a for a in exists if exists[a]]))
 
     # are there any packages which have a maintainer, but don't exist?
-    mlist = maintainers.Maintainer.read(args)
+    mlist = maintainers.Maintainer.read(args, getattr(args, 'orphanmaint', None))
     all_packages = maintainers.Maintainer.all_packages(mlist)
 
     for p in sorted(all_packages):
diff --git a/calm/maintainers.py b/calm/maintainers.py
index 740f61d..b9c51fd 100644
--- a/calm/maintainers.py
+++ b/calm/maintainers.py
@@ -35,6 +35,12 @@
 # - the timestamp when 'ignoring' warnings were last emitted
 #
 
+# XXX: Rather than this implementing an object which reads cygwin-pkg-maint when
+# constructed at specific places in the code, perhaps this needs to contain the
+# list (and it's inversion) and accessors, and invalidate that stored list when
+# cygwin-pkg-maint changes...
+
+from collections import defaultdict
 import itertools
 import logging
 import os
@@ -193,13 +199,26 @@ class Maintainer(object):
 
     # create maintainer list
     @staticmethod
-    def read(args):
+    def read(args, orphanmaint=None):
         mlist = {}
         mlist = Maintainer.add_directories(mlist, args.homedir)
-        mlist = Maintainer.add_packages(mlist, args.pkglist, getattr(args, 'orphanmaint', None))
+        mlist = Maintainer.add_packages(mlist, args.pkglist, orphanmaint)
 
         return mlist
 
+    # invert to a per-package list of maintainers
+    @staticmethod
+    def invert(mlist):
+        _pkgs = defaultdict(list)
+        # for each maintainer
+        for m in mlist.values():
+            # for each package
+            for p in m.pkgs:
+                # add the maintainer name
+                _pkgs[p].append(m.name)
+
+        return _pkgs
+
     @staticmethod
     def update_reminder_times(mlist):
         for m in mlist.values():
diff --git a/calm/pkg2html.py b/calm/pkg2html.py
index 6320c83..be64c6c 100755
--- a/calm/pkg2html.py
+++ b/calm/pkg2html.py
@@ -30,6 +30,7 @@
 # -- for each tar file
 # --- if a package listing HTML file doesn't already exist
 # ---- write a HTML package listing file listing the tar file contents
+# -- write a summary file, if set of versions changed
 # - write packages.inc, the list of packages
 # - remove any .htaccess or listing files for which there was no package
 # - remove any directories which are now empty
@@ -50,7 +51,9 @@ import tarfile
 import textwrap
 import time
 
+from .version import SetupVersion
 from . import common_constants
+from . import maintainers
 from . import package
 
 
@@ -61,7 +64,7 @@ from . import package
 # 'skip':', in which case we try to make a reasonable one
 #
 
-def desc(packages, p, bv):
+def sdesc(packages, p, bv):
     if 'sdesc' in packages[p].version_hints[bv]:
         header = packages[p].version_hints[bv]['sdesc']
     else:
@@ -70,17 +73,196 @@ def desc(packages, p, bv):
     return header.replace('"', '')
 
 
+# ditto for ldesc
+
+def ldesc(packages, p, bv):
+    if 'ldesc' in packages[p].version_hints[bv]:
+        header = packages[p].version_hints[bv]['ldesc']
+    else:
+        header = p
+
+    return header.replace('"', '')
+
+
+# ensure a directory exists
 #
-#
-#
+# for some versions of python, os.makedirs() can still raise FileExistsError
+# even when exists_ok=True, if the directory mode is not as expected.
 
-def update_package_listings(args, packages, arch):
-    base = os.path.join(args.htdocs, arch)
+def ensure_dir_exists(args, path):
     if not args.dryrun:
         try:
-            os.makedirs(base, exist_ok=True)
+            os.makedirs(path, exist_ok=True)
         except FileExistsError:
             pass
+        os.chmod(path, 0o755)
+
+
+#
+#
+#
+
+def update_package_listings(args, packages):
+    package_list = set()
+    update_summary = set()
+
+    for arch in packages:
+        update_summary.update(write_arch_listing(args, packages[arch], arch))
+        package_list.update(packages[arch])
+
+    summaries = os.path.join(args.htdocs, 'summary')
+    ensure_dir_exists(args, summaries)
+
+    mlist = maintainers.Maintainer.read(args, None)
+    pkg_maintainers = maintainers.Maintainer.invert(mlist)
+
+    toremove = glob.glob(os.path.join(summaries, '*'))
+
+    def linkify_package(p):
+        if p in package_list:
+            return '<a href="%s.html">%s</a>' % (p, p)
+        logging.debug('package linkification failed for %s' % p)
+        return p
+
+    for p in package_list:
+        #
+        # write package summary
+        #
+        # (these exist in a separate directory to prevent their contents being
+        # searched by the package search script)
+        #
+        summary = os.path.join(summaries, p + '.html')
+
+        # this file should exist, so remove from the toremove list
+        if summary in toremove:
+            toremove.remove(summary)
+
+        # if listing files were added or removed, or it doesn't already exist,
+        # or force, update the summary
+        if p in update_summary or not os.path.exists(summary) or args.force:
+            logging.debug('writing %s' % summary)
+            if not args.dryrun:
+                with open(summary, 'w') as f:
+
+                    arch_packages = None
+                    for arch in common_constants.ARCHES:
+                        if p in packages[arch]:
+                            arch_packages = packages[arch]
+                            break
+
+                    if not arch_packages:
+                        continue
+
+                    bv = arch_packages[p].best_version
+                    title = "Cygwin Package Summary for %s" % p
+
+                    print(textwrap.dedent('''\
+                    <!DOCTYPE html>
+                    <html>
+                    <head>
+                    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+                    <link rel="stylesheet" type="text/css" href="../../style.css"/>
+                    <title>%s</title>
+                    </head>
+                    <body>
+                    <div id="main">
+                    <h1>Package: %s</h1>''' % (title, p)), file=f)
+
+                    print('<span class="detail">sdesc</span>: %s<br><br>' % sdesc(arch_packages, p, bv), file=f)
+                    print('<span class="detail">ldesc</span>: %s<br><br>' % ldesc(arch_packages, p, bv), file=f)
+                    print('<span class="detail">categories</span>: %s<br><br>' % arch_packages[p].version_hints[bv].get('category', ''), file=f)
+
+                    for key in ['depends', 'obsoletes', 'provides', 'conflicts', 'build-depends']:
+                        value = arch_packages[p].version_hints[bv].get(key, None)
+                        if value:
+                            print('<span class="detail">%s</span>: %s<br><br>' % (key, ', '.join([linkify_package(p) for p in value.split(', ')])), file=f)
+
+                    es = arch_packages[p].version_hints[bv].get('external-source', None)
+                    if es:
+                        print('<span class="detail">source</span>: %s<br><br>' % linkify_package(es), file=f)
+                    else:
+                        print('<span class="detail">binaries</span>: %s<br><br>' % ', '.join([linkify_package(p) for p in sorted(arch_packages[p].is_used_by)]), file=f)
+                        es = p
+
+                    print('<span class="detail">maintainer(s)</span>: %s ' % ', '.join(sorted(pkg_maintainers[es])), file=f)
+                    print(textwrap.dedent('''\
+                    <span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+                    <a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>'''), file=f)
+                    print('<br><br>', file=f)
+
+                    print('<ul>', file=f)
+                    for arch in packages:
+                        if p in packages[arch]:
+
+                            print('<li><span class="detail">%s</span></li>' % arch, file=f)
+
+                            print('<table class="pkgtable">', file=f)
+                            print('<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>', file=f)
+
+                            def tar_line(pn, p, category, v, arch, f):
+                                if category not in p.vermap[v]:
+                                    return
+                                t = p.vermap[v][category]
+                                size = round(p.tar(v, category).size / 1024)
+                                name = v if category == 'install' else v + ' (source)'
+                                target = "%s-%s" % (pn, v) + ('' if category == 'install' else '-src')
+                                print('<tr><td>%s</td><td class="right">%d kB</td><td>[<a href="../%s/%s/%s">list of files</a>]</td></tr>' % (name, size, arch, pn, target), file=f)
+
+                            for version in sorted(packages[arch][p].vermap.keys(), key=lambda v: SetupVersion(v)):
+                                tar_line(p, packages[arch][p], 'install', version, arch, f)
+                                tar_line(p, packages[arch][p], 'source', version, arch, f)
+
+                            print('</table><br>', file=f)
+                    print('</ul>', file=f)
+
+                    print(textwrap.dedent('''\
+                    </div>
+                    </body>
+                    </html>'''), file=f)
+
+    for r in toremove:
+        logging.debug('rm %s' % r)
+        if not args.dryrun:
+            os.unlink(r)
+
+    #
+    # write packages.inc
+    #
+
+    packages_inc = os.path.join(args.htdocs, 'packages.inc')
+    logging.debug('writing %s' % packages_inc)
+    if not args.dryrun:
+        with open(packages_inc, 'w') as index:
+            os.fchmod(index.fileno(), 0o755)
+            print(textwrap.dedent('''\
+                                     <h2 class="cartouche">Available Packages</h2>
+                                     <table class="pkglist">'''), file=index)
+
+            for p in sorted(package_list, key=package.sort_key):
+
+                arch_packages = None
+                for arch in common_constants.ARCHES:
+                    if p in packages[arch]:
+                        arch_packages = packages[arch]
+                        break
+
+                if not arch_packages:
+                    continue
+
+                bv = arch_packages[p].best_version
+                header = sdesc(arch_packages, p, bv)
+
+                print('<tr><td><a href="summary' + '/' + p + '.html">' + p + '</a></td><td>' + html.escape(header, quote=False) + '</td></tr>', file=index)
+
+            print(textwrap.dedent('''\
+                                     </table>
+                                     '''), file=index)
+
+
+def write_arch_listing(args, packages, arch):
+    update_summary = set()
+    base = os.path.join(args.htdocs, arch)
+    ensure_dir_exists(args, base)
 
     #
     # write base directory .htaccess, if needed
@@ -105,12 +287,7 @@ def update_package_listings(args, packages, arch):
     for p in packages:
 
         dir = os.path.join(base, p)
-        if not args.dryrun:
-            try:
-                os.makedirs(dir, exist_ok=True)
-            except FileExistsError:
-                pass
-            os.chmod(dir, 0o777)
+        ensure_dir_exists(args, dir)
 
         #
         # write .htaccess if needed
@@ -138,7 +315,7 @@ def update_package_listings(args, packages, arch):
         #
         # for each tarfile, write tarfile listing
         #
-
+        listings = os.listdir(dir)
         for t in itertools.chain.from_iterable([packages[p].tars[vr] for vr in packages[p].tars]):
             fver = re.sub(r'\.tar.*$', '', t)
             listing = os.path.join(dir, fver)
@@ -149,9 +326,12 @@ def update_package_listings(args, packages, arch):
                 logging.debug('writing %s' % listing)
 
                 if not args.dryrun:
+                    # versions are being added, so summary needs updating
+                    update_summary.add(p)
+
                     with open(listing, 'w') as f:
                         bv = packages[p].best_version
-                        header = p + ": " + desc(packages, p, bv)
+                        header = p + ": " + sdesc(packages, p, bv)
 
                         if fver.endswith('-src'):
                             header = header + " (source code)"
@@ -202,30 +382,13 @@ def update_package_listings(args, packages, arch):
             if listing in toremove:
                 toremove.remove(listing)
 
-    #
-    # write packages.inc
-    #
+            if fver in listings:
+                listings.remove(fver)
 
-    packages_inc = os.path.join(base, 'packages.inc')
-    logging.debug('writing %s' % packages_inc)
-    if not args.dryrun:
-        with open(packages_inc, 'w') as index:
-            os.fchmod(index.fileno(), 0o755)
-            print(textwrap.dedent('''\
-                                     <div id="%s">
-                                     <h2 class="cartouche">Available Packages for %s</h2>
-                                     <table class="pkglist">''') % (arch, arch), file=index)
-
-            for p in sorted(packages.keys(), key=package.sort_key):
-
-                bv = packages[p].best_version
-                header = desc(packages, p, bv)
-
-                print('<tr><td><a href="' + arch + '/' + p + '">' + p + '</a></td><td>' + html.escape(header, quote=False) + '</td></tr>', file=index)
-
-            print(textwrap.dedent('''\
-                                     </table>
-                                     </div>'''), file=index)
+        # some versions remain on toremove list, and will be removed, so summary
+        # needs updating
+        if listings:
+            update_summary.add(p)
 
     #
     # remove any remaining files for which there was no corresponding package
@@ -245,6 +408,8 @@ def update_package_listings(args, packages, arch):
                 logging.debug('rmdir %s' % dirpath)
                 os.rmdir(os.path.join(dirpath))
 
+    return update_summary
+
 
 if __name__ == "__main__":
     htdocs_default = os.path.join(common_constants.HTDOCS, 'packages')
diff --git a/test/test_calm.py b/test/test_calm.py
index 322d776..80b8e4e 100755
--- a/test/test_calm.py
+++ b/test/test_calm.py
@@ -151,13 +151,15 @@ class CalmTest(unittest.TestCase):
         setattr(args, 'arch', 'x86')
         setattr(args, 'htdocs', htdocs)
         setattr(args, 'rel_area', 'testdata/relarea')
+        setattr(args, 'homedir', 'testdata/homes')
         setattr(args, 'dryrun', False)
         setattr(args, 'force', True)
         setattr(args, 'pkglist', 'testdata/pkglist/cygwin-pkg-maint')
 
-        packages = package.read_packages(args.rel_area, args.arch)
-        package.validate_packages(args, packages)
-        pkg2html.update_package_listings(args, packages, args.arch)
+        packages = {}
+        packages[args.arch] = package.read_packages(args.rel_area, args.arch)
+        package.validate_packages(args, packages[args.arch])
+        pkg2html.update_package_listings(args, packages)
 
         # compare the output files with expected
         for (dirpath, subdirs, files) in os.walk(htdocs):
@@ -393,7 +395,7 @@ class CalmTest(unittest.TestCase):
         packages = calm.calm.process(args, state)
         self.assertTrue(packages)
 
-        pkg2html.update_package_listings(args, packages['x86'], 'x86')
+        pkg2html.update_package_listings(args, packages)
         package.write_setup_ini(args, packages['x86'], 'x86')
 
         with open(os.path.join(args.rel_area, 'setup.ini')) as inifile:
diff --git a/test/testdata/htdocs.expected/packages.inc b/test/testdata/htdocs.expected/packages.inc
new file mode 100755
index 0000000..ad4d882
--- /dev/null
+++ b/test/testdata/htdocs.expected/packages.inc
@@ -0,0 +1,26 @@
+<h2 class="cartouche">Available Packages</h2>
+<table class="pkglist">
+<tr><td><a href="summary/arc.html">arc</a></td><td>The ARC archive utility</td></tr>
+<tr><td><a href="summary/base-cygwin.html">base-cygwin</a></td><td>Initial base installation helper script</td></tr>
+<tr><td><a href="summary/corrupt.html">corrupt</a></td><td>A corrupt package</td></tr>
+<tr><td><a href="summary/cygwin.html">cygwin</a></td><td>The UNIX emulation engine</td></tr>
+<tr><td><a href="summary/cygwin-debuginfo.html">cygwin-debuginfo</a></td><td>Debug info for cygwin</td></tr>
+<tr><td><a href="summary/cygwin-devel.html">cygwin-devel</a></td><td>Core development files</td></tr>
+<tr><td><a href="summary/keychain.html">keychain</a></td><td>Key manager for OpenSSH</td></tr>
+<tr><td><a href="summary/libdns_sd-devel.html">libdns_sd-devel</a></td><td>Bonjour Zeroconf implementation</td></tr>
+<tr><td><a href="summary/libdns_sd1.html">libdns_sd1</a></td><td>Bonjour Zeroconf implementation</td></tr>
+<tr><td><a href="summary/mDNSResponder.html">mDNSResponder</a></td><td>Bonjour Zeroconf implementation</td></tr>
+<tr><td><a href="summary/obs-a.html">obs-a</a></td><td>obsolete package A</td></tr>
+<tr><td><a href="summary/obs-b.html">obs-b</a></td><td>obsolete package B</td></tr>
+<tr><td><a href="summary/openssh.html">openssh</a></td><td>The OpenSSH server and client programs</td></tr>
+<tr><td><a href="summary/per-version.html">per-version</a></td><td>Per-version hint test package</td></tr>
+<tr><td><a href="summary/per-version-replacement-hint-only.html">per-version-replacement-hint-only</a></td><td>Per-version hint test package</td></tr>
+<tr><td><a href="summary/perl-Net-SMTP-SSL.html">perl-Net-SMTP-SSL</a></td><td>Perl distribution Net-SMTP-SSL</td></tr>
+<tr><td><a href="summary/rpm-doc.html">rpm-doc</a></td><td>Obsolete package for RPM package management system manual pages (extra text to so repr is not one line)</td></tr>
+<tr><td><a href="summary/staleversion.html">staleversion</a></td><td>Test package for stale version removal</td></tr>
+<tr><td><a href="summary/test-c.html">test-c</a></td><td>test package C</td></tr>
+<tr><td><a href="summary/test-d.html">test-d</a></td><td>test package D</td></tr>
+<tr><td><a href="summary/test-e.html">test-e</a></td><td>test package E</td></tr>
+<tr><td><a href="summary/testpackage.html">testpackage</a></td><td>A test package (stuff &amp; other stuff)</td></tr>
+</table>
+
diff --git a/test/testdata/htdocs.expected/summary/arc.html b/test/testdata/htdocs.expected/summary/arc.html
new file mode 100644
index 0000000..6f13aef
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/arc.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for arc</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: arc</h1>
+<span class="detail">sdesc</span>: The ARC archive utility<br><br>
+<span class="detail">ldesc</span>: This program is based on the MSDOS ARC program, version 5.21, plus a
+few enhancements. ARC performs Huffman Squeezing on data. The Huffman
+Squeeze algorithm was removed from MSDOS ARC after version 5.12. It
+turns out to be more efficient than Lempel-Ziv style compression when
+compressing graphic images. Squeeze analysis is always done now, and
+the best of packing, squeezing, or crunching is used.<br><br>
+<span class="detail">categories</span>: Archive<br><br>
+<span class="detail">binaries</span>: <a href="arc.html">arc</a><br><br>
+<span class="detail">maintainer(s)</span>: Jari Aalto 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>4.32.7-10</td><td class="right">1 kB</td><td>[<a href="../x86/arc/arc-4.32.7-10">list of files</a>]</td></tr>
+<tr><td>4.32.7-10 (source)</td><td class="right">1 kB</td><td>[<a href="../x86/arc/arc-4.32.7-10-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/base-cygwin.html b/test/testdata/htdocs.expected/summary/base-cygwin.html
new file mode 100644
index 0000000..fc6b266
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/base-cygwin.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for base-cygwin</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: base-cygwin</h1>
+<span class="detail">sdesc</span>: Initial base installation helper script<br><br>
+<span class="detail">ldesc</span>: Initial base installation helper script.<br><br>
+<span class="detail">categories</span>: Base<br><br>
+<span class="detail">binaries</span>: <br><br>
+<span class="detail">maintainer(s)</span>: Corinna Vinschen 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>3.6-1</td><td class="right">0 kB</td><td>[<a href="../x86/base-cygwin/base-cygwin-3.6-1">list of files</a>]</td></tr>
+<tr><td>3.8-1</td><td class="right">0 kB</td><td>[<a href="../x86/base-cygwin/base-cygwin-3.8-1">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/corrupt.html b/test/testdata/htdocs.expected/summary/corrupt.html
new file mode 100644
index 0000000..80316d5
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/corrupt.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for corrupt</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: corrupt</h1>
+<span class="detail">sdesc</span>: A corrupt package<br><br>
+<span class="detail">ldesc</span>: A package containing corrupt archives<br><br>
+<span class="detail">categories</span>: Devel<br><br>
+<span class="detail">binaries</span>: <a href="corrupt.html">corrupt</a><br><br>
+<span class="detail">maintainer(s)</span>: Blooey McFooey 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>2.0.0-1</td><td class="right">0 kB</td><td>[<a href="../x86/corrupt/corrupt-2.0.0-1">list of files</a>]</td></tr>
+<tr><td>2.0.0-1 (source)</td><td class="right">354 kB</td><td>[<a href="../x86/corrupt/corrupt-2.0.0-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/cygwin-debuginfo.html b/test/testdata/htdocs.expected/summary/cygwin-debuginfo.html
new file mode 100644
index 0000000..f311971
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/cygwin-debuginfo.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for cygwin-debuginfo</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: cygwin-debuginfo</h1>
+<span class="detail">sdesc</span>: Debug info for cygwin<br><br>
+<span class="detail">ldesc</span>: This package contains files necessary for debugging the
+cygwin package with gdb.<br><br>
+<span class="detail">categories</span>: Debug<br><br>
+<span class="detail">depends</span>: <a href="cygwin-debuginfo.html">cygwin-debuginfo</a><br><br>
+<span class="detail">source</span>: <a href="cygwin.html">cygwin</a><br><br>
+<span class="detail">maintainer(s)</span>: Corinna Vinschen, Yaakov Selkowitz 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>2.2.0-1</td><td class="right">0 kB</td><td>[<a href="../x86/cygwin-debuginfo/cygwin-debuginfo-2.2.0-1">list of files</a>]</td></tr>
+<tr><td>2.2.1-1</td><td class="right">0 kB</td><td>[<a href="../x86/cygwin-debuginfo/cygwin-debuginfo-2.2.1-1">list of files</a>]</td></tr>
+<tr><td>2.3.0-0.3</td><td class="right">0 kB</td><td>[<a href="../x86/cygwin-debuginfo/cygwin-debuginfo-2.3.0-0.3">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/cygwin-devel.html b/test/testdata/htdocs.expected/summary/cygwin-devel.html
new file mode 100644
index 0000000..1576218
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/cygwin-devel.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for cygwin-devel</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: cygwin-devel</h1>
+<span class="detail">sdesc</span>: Core development files<br><br>
+<span class="detail">ldesc</span>: Core development files required to build Cygwin packages<br><br>
+<span class="detail">categories</span>: Devel<br><br>
+<span class="detail">source</span>: <a href="cygwin.html">cygwin</a><br><br>
+<span class="detail">maintainer(s)</span>: Corinna Vinschen, Yaakov Selkowitz 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>2.2.0-1</td><td class="right">0 kB</td><td>[<a href="../x86/cygwin-devel/cygwin-devel-2.2.0-1">list of files</a>]</td></tr>
+<tr><td>2.2.1-1</td><td class="right">0 kB</td><td>[<a href="../x86/cygwin-devel/cygwin-devel-2.2.1-1">list of files</a>]</td></tr>
+<tr><td>2.3.0-0.3</td><td class="right">0 kB</td><td>[<a href="../x86/cygwin-devel/cygwin-devel-2.3.0-0.3">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/cygwin.html b/test/testdata/htdocs.expected/summary/cygwin.html
new file mode 100644
index 0000000..187b9da
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/cygwin.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for cygwin</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: cygwin</h1>
+<span class="detail">sdesc</span>: The UNIX emulation engine<br><br>
+<span class="detail">ldesc</span>: The UNIX emulation engine<br><br>
+<span class="detail">categories</span>: Base<br><br>
+<span class="detail">depends</span>: <a href="base-cygwin.html">base-cygwin</a><br><br>
+<span class="detail">binaries</span>: <a href="cygwin.html">cygwin</a>, <a href="cygwin-debuginfo.html">cygwin-debuginfo</a>, <a href="cygwin-devel.html">cygwin-devel</a><br><br>
+<span class="detail">maintainer(s)</span>: Corinna Vinschen, Yaakov Selkowitz 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>2.2.0-1</td><td class="right">0 kB</td><td>[<a href="../x86/cygwin/cygwin-2.2.0-1">list of files</a>]</td></tr>
+<tr><td>2.2.0-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/cygwin/cygwin-2.2.0-1-src">list of files</a>]</td></tr>
+<tr><td>2.2.1-1</td><td class="right">0 kB</td><td>[<a href="../x86/cygwin/cygwin-2.2.1-1">list of files</a>]</td></tr>
+<tr><td>2.2.1-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/cygwin/cygwin-2.2.1-1-src">list of files</a>]</td></tr>
+<tr><td>2.3.0-0.3</td><td class="right">0 kB</td><td>[<a href="../x86/cygwin/cygwin-2.3.0-0.3">list of files</a>]</td></tr>
+<tr><td>2.3.0-0.3 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/cygwin/cygwin-2.3.0-0.3-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/keychain.html b/test/testdata/htdocs.expected/summary/keychain.html
new file mode 100644
index 0000000..c4e8ce7
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/keychain.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for keychain</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: keychain</h1>
+<span class="detail">sdesc</span>: Key manager for OpenSSH<br><br>
+<span class="detail">ldesc</span>: Keychain is an OpenSSH key manager, typically run from
+~/.bash_profile. When keychain is run, it checks for a running
+ssh-agent, otherwise it starts one. It saves the ssh-agent environment
+variables to ~/.keychain/$HOSTNAME-sh, so that subsequent logins
+and non-interactive shells such as cron jobs can source the file and
+make passwordless ssh connections. In addition, when keychain runs, it
+verifies that the key files specified on the command-line are known to
+ssh-agent, otherwise it loads them, prompting you for a password if
+necessary<br><br>
+<span class="detail">categories</span>: Utils<br><br>
+<span class="detail">depends</span>: <a href="openssh.html">openssh</a><br><br>
+<span class="detail">binaries</span>: <a href="keychain.html">keychain</a><br><br>
+<span class="detail">maintainer(s)</span>: Jari Aalto 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>2.6.8-1</td><td class="right">30 kB</td><td>[<a href="../x86/keychain/keychain-2.6.8-1">list of files</a>]</td></tr>
+<tr><td>2.6.8-1 (source)</td><td class="right">35 kB</td><td>[<a href="../x86/keychain/keychain-2.6.8-1-src">list of files</a>]</td></tr>
+<tr><td>2.7.1-1</td><td class="right">31 kB</td><td>[<a href="../x86/keychain/keychain-2.7.1-1">list of files</a>]</td></tr>
+<tr><td>2.7.1-1 (source)</td><td class="right">132 kB</td><td>[<a href="../x86/keychain/keychain-2.7.1-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/libdns_sd-devel.html b/test/testdata/htdocs.expected/summary/libdns_sd-devel.html
new file mode 100644
index 0000000..0678e5c
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/libdns_sd-devel.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for libdns_sd-devel</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: libdns_sd-devel</h1>
+<span class="detail">sdesc</span>: Bonjour Zeroconf implementation<br><br>
+<span class="detail">ldesc</span>: Bonjour, also known as zero-configuration networking, enables
+automatic discovery of computers, devices, and services on IP networks using
+industry standard IP protocols.<br><br>
+<span class="detail">categories</span>: Net<br><br>
+<span class="detail">depends</span>: <a href="libdns_sd1.html">libdns_sd1</a><br><br>
+<span class="detail">source</span>: <a href="mDNSResponder.html">mDNSResponder</a><br><br>
+<span class="detail">maintainer(s)</span>: Yaakov Selkowitz 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>379.32.1-1</td><td class="right">0 kB</td><td>[<a href="../x86/libdns_sd-devel/libdns_sd-devel-379.32.1-1">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/libdns_sd1.html b/test/testdata/htdocs.expected/summary/libdns_sd1.html
new file mode 100644
index 0000000..cfe6a56
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/libdns_sd1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for libdns_sd1</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: libdns_sd1</h1>
+<span class="detail">sdesc</span>: Bonjour Zeroconf implementation<br><br>
+<span class="detail">ldesc</span>: Bonjour, also known as zero-configuration networking, enables
+automatic discovery of computers, devices, and services on IP networks using
+industry standard IP protocols.<br><br>
+<span class="detail">categories</span>: Net<br><br>
+<span class="detail">source</span>: <a href="mDNSResponder.html">mDNSResponder</a><br><br>
+<span class="detail">maintainer(s)</span>: Yaakov Selkowitz 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>379.32.1-1</td><td class="right">0 kB</td><td>[<a href="../x86/libdns_sd1/libdns_sd1-379.32.1-1">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/mDNSResponder.html b/test/testdata/htdocs.expected/summary/mDNSResponder.html
new file mode 100644
index 0000000..746101e
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/mDNSResponder.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for mDNSResponder</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: mDNSResponder</h1>
+<span class="detail">sdesc</span>: Bonjour Zeroconf implementation<br><br>
+<span class="detail">ldesc</span>: Bonjour, also known as zero-configuration networking, enables
+automatic discovery of computers, devices, and services on IP networks using
+industry standard IP protocols.<br><br>
+<span class="detail">categories</span>: Net<br><br>
+<span class="detail">depends</span>: <a href="libdns_sd1.html">libdns_sd1</a><br><br>
+<span class="detail">binaries</span>: <a href="libdns_sd-devel.html">libdns_sd-devel</a>, <a href="libdns_sd1.html">libdns_sd1</a>, <a href="mDNSResponder.html">mDNSResponder</a><br><br>
+<span class="detail">maintainer(s)</span>: Yaakov Selkowitz 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>379.32.1-1</td><td class="right">0 kB</td><td>[<a href="../x86/mDNSResponder/mDNSResponder-379.32.1-1">list of files</a>]</td></tr>
+<tr><td>379.32.1-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/mDNSResponder/mDNSResponder-379.32.1-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/obs-a.html b/test/testdata/htdocs.expected/summary/obs-a.html
new file mode 100644
index 0000000..e2591e6
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/obs-a.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for obs-a</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: obs-a</h1>
+<span class="detail">sdesc</span>: obsolete package A<br><br>
+<span class="detail">ldesc</span>: obs-a<br><br>
+<span class="detail">categories</span>: Devel<br><br>
+<span class="detail">binaries</span>: <a href="obs-a.html">obs-a</a><br><br>
+<span class="detail">maintainer(s)</span>: ORPHANED 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>1.0-1</td><td class="right">0 kB</td><td>[<a href="../x86/obs-a/obs-a-1.0-1">list of files</a>]</td></tr>
+<tr><td>1.0-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/obs-a/obs-a-1.0-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/obs-b.html b/test/testdata/htdocs.expected/summary/obs-b.html
new file mode 100644
index 0000000..8de2270
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/obs-b.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for obs-b</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: obs-b</h1>
+<span class="detail">sdesc</span>: obsolete package B<br><br>
+<span class="detail">ldesc</span>: obs-b<br><br>
+<span class="detail">categories</span>: Devel<br><br>
+<span class="detail">binaries</span>: <a href="obs-b.html">obs-b</a><br><br>
+<span class="detail">maintainer(s)</span>: ORPHANED 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>1.0-1</td><td class="right">0 kB</td><td>[<a href="../x86/obs-b/obs-b-1.0-1">list of files</a>]</td></tr>
+<tr><td>1.0-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/obs-b/obs-b-1.0-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/openssh.html b/test/testdata/htdocs.expected/summary/openssh.html
new file mode 100644
index 0000000..334d96c
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/openssh.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for openssh</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: openssh</h1>
+<span class="detail">sdesc</span>: The OpenSSH server and client programs<br><br>
+<span class="detail">ldesc</span>: OpenSSH is a program for logging into a remote machine and for
+	executing commands on a remote machine.  It can replace rlogin and rsh,
+	providing encrypted communication between two machines.<br><br>
+<span class="detail">categories</span>: Net<br><br>
+<span class="detail">binaries</span>: <a href="openssh.html">openssh</a><br><br>
+<span class="detail">maintainer(s)</span>: Corinna Vinschen 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>7.2p2-1</td><td class="right">0 kB</td><td>[<a href="../x86/openssh/openssh-7.2p2-1">list of files</a>]</td></tr>
+<tr><td>7.2p2-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/openssh/openssh-7.2p2-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/per-version-replacement-hint-only.html b/test/testdata/htdocs.expected/summary/per-version-replacement-hint-only.html
new file mode 100644
index 0000000..3bfc642
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/per-version-replacement-hint-only.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for per-version-replacement-hint-only</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: per-version-replacement-hint-only</h1>
+<span class="detail">sdesc</span>: Per-version hint test package<br><br>
+<span class="detail">ldesc</span>: Per-version hint test package<br><br>
+<span class="detail">categories</span>: Base<br><br>
+<span class="detail">depends</span>: <a href="cygwin.html">cygwin</a><br><br>
+<span class="detail">binaries</span>: <a href="per-version-replacement-hint-only.html">per-version-replacement-hint-only</a><br><br>
+<span class="detail">maintainer(s)</span>: Blooey McFooey 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>1.0-1</td><td class="right">0 kB</td><td>[<a href="../x86/per-version-replacement-hint-only/per-version-replacement-hint-only-1.0-1">list of files</a>]</td></tr>
+<tr><td>1.0-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/per-version-replacement-hint-only/per-version-replacement-hint-only-1.0-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/per-version.html b/test/testdata/htdocs.expected/summary/per-version.html
new file mode 100644
index 0000000..f179c85
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/per-version.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for per-version</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: per-version</h1>
+<span class="detail">sdesc</span>: Per-version hint test package<br><br>
+<span class="detail">ldesc</span>: Per-version hint test package<br><br>
+<span class="detail">categories</span>: Base<br><br>
+<span class="detail">depends</span>: <a href="base-cygwin.html">base-cygwin</a><br><br>
+<span class="detail">binaries</span>: <a href="per-version.html">per-version</a><br><br>
+<span class="detail">maintainer(s)</span>: Blooey McFooey 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>4.0-1</td><td class="right">0 kB</td><td>[<a href="../x86/per-version/per-version-4.0-1">list of files</a>]</td></tr>
+<tr><td>4.0-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/per-version/per-version-4.0-1-src">list of files</a>]</td></tr>
+<tr><td>4.8-1</td><td class="right">0 kB</td><td>[<a href="../x86/per-version/per-version-4.8-1">list of files</a>]</td></tr>
+<tr><td>4.8-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/per-version/per-version-4.8-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/perl-Net-SMTP-SSL.html b/test/testdata/htdocs.expected/summary/perl-Net-SMTP-SSL.html
new file mode 100644
index 0000000..03580b7
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/perl-Net-SMTP-SSL.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for perl-Net-SMTP-SSL</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: perl-Net-SMTP-SSL</h1>
+<span class="detail">sdesc</span>: Perl distribution Net-SMTP-SSL<br><br>
+<span class="detail">ldesc</span>: Implements the same API as Net::SMTP, but uses IO::Socket::SSL for
+its network operations in order to support encrypted connections.<br><br>
+<span class="detail">categories</span>: Perl<br><br>
+<span class="detail">binaries</span>: <a href="perl-Net-SMTP-SSL.html">perl-Net-SMTP-SSL</a><br><br>
+<span class="detail">maintainer(s)</span>: Blooey McFooey, Yaakov Selkowitz 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>1.03-1</td><td class="right">3 kB</td><td>[<a href="../x86/perl-Net-SMTP-SSL/perl-Net-SMTP-SSL-1.03-1">list of files</a>]</td></tr>
+<tr><td>1.03-1 (source)</td><td class="right">3 kB</td><td>[<a href="../x86/perl-Net-SMTP-SSL/perl-Net-SMTP-SSL-1.03-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/rpm-doc.html b/test/testdata/htdocs.expected/summary/rpm-doc.html
new file mode 100644
index 0000000..190c8f3
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/rpm-doc.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for rpm-doc</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: rpm-doc</h1>
+<span class="detail">sdesc</span>: Obsolete package for RPM package management system manual pages (extra text to so repr is not one line)<br><br>
+<span class="detail">ldesc</span>: rpm-doc<br><br>
+<span class="detail">categories</span>: _obsolete<br><br>
+<span class="detail">binaries</span>: <a href="rpm-doc.html">rpm-doc</a><br><br>
+<span class="detail">maintainer(s)</span>:  
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>4.1-2</td><td class="right">50 kB</td><td>[<a href="../x86/rpm-doc/rpm-doc-4.1-2">list of files</a>]</td></tr>
+<tr><td>4.1-2 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/rpm-doc/rpm-doc-4.1-2-src">list of files</a>]</td></tr>
+<tr><td>999-1</td><td class="right">0 kB</td><td>[<a href="../x86/rpm-doc/rpm-doc-999-1">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/staleversion.html b/test/testdata/htdocs.expected/summary/staleversion.html
new file mode 100644
index 0000000..031ab45
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/staleversion.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for staleversion</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: staleversion</h1>
+<span class="detail">sdesc</span>: Test package for stale version removal<br><br>
+<span class="detail">ldesc</span>: Test package for stale version removal<br><br>
+<span class="detail">categories</span>: Shells Base<br><br>
+<span class="detail">binaries</span>: <a href="staleversion.html">staleversion</a><br><br>
+<span class="detail">maintainer(s)</span>: Blooey McFooey 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>240-1</td><td class="right">0 kB</td><td>[<a href="../x86/staleversion/staleversion-240-1">list of files</a>]</td></tr>
+<tr><td>240-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/staleversion/staleversion-240-1-src">list of files</a>]</td></tr>
+<tr><td>242-0</td><td class="right">0 kB</td><td>[<a href="../x86/staleversion/staleversion-242-0">list of files</a>]</td></tr>
+<tr><td>242-0 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/staleversion/staleversion-242-0-src">list of files</a>]</td></tr>
+<tr><td>243-0</td><td class="right">0 kB</td><td>[<a href="../x86/staleversion/staleversion-243-0">list of files</a>]</td></tr>
+<tr><td>243-0 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/staleversion/staleversion-243-0-src">list of files</a>]</td></tr>
+<tr><td>250-0</td><td class="right">0 kB</td><td>[<a href="../x86/staleversion/staleversion-250-0">list of files</a>]</td></tr>
+<tr><td>250-0 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/staleversion/staleversion-250-0-src">list of files</a>]</td></tr>
+<tr><td>251-0</td><td class="right">0 kB</td><td>[<a href="../x86/staleversion/staleversion-251-0">list of files</a>]</td></tr>
+<tr><td>251-0 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/staleversion/staleversion-251-0-src">list of files</a>]</td></tr>
+<tr><td>260-0</td><td class="right">0 kB</td><td>[<a href="../x86/staleversion/staleversion-260-0">list of files</a>]</td></tr>
+<tr><td>260-0 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/staleversion/staleversion-260-0-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/test-c.html b/test/testdata/htdocs.expected/summary/test-c.html
new file mode 100644
index 0000000..cf3757c
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/test-c.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for test-c</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: test-c</h1>
+<span class="detail">sdesc</span>: test package C<br><br>
+<span class="detail">ldesc</span>: test-c<br><br>
+<span class="detail">categories</span>: Devel<br><br>
+<span class="detail">depends</span>: test-d (>= 1.0), <a href="test-e.html">test-e</a><br><br>
+<span class="detail">obsoletes</span>: <a href="obs-a.html">obs-a</a>, <a href="obs-b.html">obs-b</a><br><br>
+<span class="detail">binaries</span>: <a href="test-c.html">test-c</a><br><br>
+<span class="detail">maintainer(s)</span>: ORPHANED 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>1.0-1</td><td class="right">0 kB</td><td>[<a href="../x86/test-c/test-c-1.0-1">list of files</a>]</td></tr>
+<tr><td>1.0-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/test-c/test-c-1.0-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/test-d.html b/test/testdata/htdocs.expected/summary/test-d.html
new file mode 100644
index 0000000..dd13f6e
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/test-d.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for test-d</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: test-d</h1>
+<span class="detail">sdesc</span>: test package D<br><br>
+<span class="detail">ldesc</span>: test-d<br><br>
+<span class="detail">categories</span>: Devel<br><br>
+<span class="detail">binaries</span>: <a href="test-d.html">test-d</a><br><br>
+<span class="detail">maintainer(s)</span>: ORPHANED 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>1.0.42590-1</td><td class="right">0 kB</td><td>[<a href="../x86/test-d/test-d-1.0.42590-1">list of files</a>]</td></tr>
+<tr><td>1.0.42590-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/test-d/test-d-1.0.42590-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/test-e.html b/test/testdata/htdocs.expected/summary/test-e.html
new file mode 100644
index 0000000..ec57c10
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/test-e.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for test-e</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: test-e</h1>
+<span class="detail">sdesc</span>: test package E<br><br>
+<span class="detail">ldesc</span>: test-e<br><br>
+<span class="detail">categories</span>: Devel<br><br>
+<span class="detail">build-depends</span>: libtextcat-devel<br><br>
+<span class="detail">binaries</span>: <a href="test-e.html">test-e</a><br><br>
+<span class="detail">maintainer(s)</span>: ORPHANED 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>1.0-1</td><td class="right">0 kB</td><td>[<a href="../x86/test-e/test-e-1.0-1">list of files</a>]</td></tr>
+<tr><td>1.0-1 (source)</td><td class="right">0 kB</td><td>[<a href="../x86/test-e/test-e-1.0-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/summary/testpackage.html b/test/testdata/htdocs.expected/summary/testpackage.html
new file mode 100644
index 0000000..6410b6e
--- /dev/null
+++ b/test/testdata/htdocs.expected/summary/testpackage.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" type="text/css" href="../../style.css"/>
+<title>Cygwin Package Summary for testpackage</title>
+</head>
+<body>
+<div id="main">
+<h1>Package: testpackage</h1>
+<span class="detail">sdesc</span>: A test package (stuff & other stuff)<br><br>
+<span class="detail">ldesc</span>: A test package (stuff & other stuff)<br><br>
+<span class="detail">categories</span>: Devel<br><br>
+<span class="detail">binaries</span>: <a href="testpackage.html">testpackage</a><br><br>
+<span class="detail">maintainer(s)</span>: Blooey McFooey 
+<span class="smaller">(Use <a href="https://cygwin.com/lists.html#cygwin">the mailing list</a> to report bugs or ask questions.
+<a href="https://cygwin.com/problems.html#personal-email">Do not contact the maintainer(s) directly</a>.)</span>
+<br><br>
+<ul>
+<li><span class="detail">x86</span></li>
+<table class="pkgtable">
+<tr><th>Version</th><th>Package Size</th><th>Files</th></tr>
+<tr><td>0.1-1</td><td class="right">1 kB</td><td>[<a href="../x86/testpackage/testpackage-0.1-1">list of files</a>]</td></tr>
+<tr><td>0.1-1 (source)</td><td class="right">1 kB</td><td>[<a href="../x86/testpackage/testpackage-0.1-1-src">list of files</a>]</td></tr>
+</table><br>
+</ul>
+</div>
+</body>
+</html>
diff --git a/test/testdata/htdocs.expected/x86/packages.inc b/test/testdata/htdocs.expected/x86/packages.inc
deleted file mode 100755
index 81bd0ec..0000000
--- a/test/testdata/htdocs.expected/x86/packages.inc
+++ /dev/null
@@ -1,27 +0,0 @@
-<div id="x86">
-<h2 class="cartouche">Available Packages for x86</h2>
-<table class="pkglist">
-<tr><td><a href="x86/arc">arc</a></td><td>The ARC archive utility</td></tr>
-<tr><td><a href="x86/base-cygwin">base-cygwin</a></td><td>Initial base installation helper script</td></tr>
-<tr><td><a href="x86/corrupt">corrupt</a></td><td>A corrupt package</td></tr>
-<tr><td><a href="x86/cygwin">cygwin</a></td><td>The UNIX emulation engine</td></tr>
-<tr><td><a href="x86/cygwin-debuginfo">cygwin-debuginfo</a></td><td>Debug info for cygwin</td></tr>
-<tr><td><a href="x86/cygwin-devel">cygwin-devel</a></td><td>Core development files</td></tr>
-<tr><td><a href="x86/keychain">keychain</a></td><td>Key manager for OpenSSH</td></tr>
-<tr><td><a href="x86/libdns_sd-devel">libdns_sd-devel</a></td><td>Bonjour Zeroconf implementation</td></tr>
-<tr><td><a href="x86/libdns_sd1">libdns_sd1</a></td><td>Bonjour Zeroconf implementation</td></tr>
-<tr><td><a href="x86/mDNSResponder">mDNSResponder</a></td><td>Bonjour Zeroconf implementation</td></tr>
-<tr><td><a href="x86/obs-a">obs-a</a></td><td>obsolete package A</td></tr>
-<tr><td><a href="x86/obs-b">obs-b</a></td><td>obsolete package B</td></tr>
-<tr><td><a href="x86/openssh">openssh</a></td><td>The OpenSSH server and client programs</td></tr>
-<tr><td><a href="x86/per-version">per-version</a></td><td>Per-version hint test package</td></tr>
-<tr><td><a href="x86/per-version-replacement-hint-only">per-version-replacement-hint-only</a></td><td>Per-version hint test package</td></tr>
-<tr><td><a href="x86/perl-Net-SMTP-SSL">perl-Net-SMTP-SSL</a></td><td>Perl distribution Net-SMTP-SSL</td></tr>
-<tr><td><a href="x86/rpm-doc">rpm-doc</a></td><td>Obsolete package for RPM package management system manual pages (extra text to so repr is not one line)</td></tr>
-<tr><td><a href="x86/staleversion">staleversion</a></td><td>Test package for stale version removal</td></tr>
-<tr><td><a href="x86/test-c">test-c</a></td><td>test package C</td></tr>
-<tr><td><a href="x86/test-d">test-d</a></td><td>test package D</td></tr>
-<tr><td><a href="x86/test-e">test-e</a></td><td>test package E</td></tr>
-<tr><td><a href="x86/testpackage">testpackage</a></td><td>A test package (stuff &amp; other stuff)</td></tr>
-</table>
-</div>
diff --git a/test/testdata/process_arch/htdocs.expected b/test/testdata/process_arch/htdocs.expected
index b0fb21c..fb09e2d 100644
--- a/test/testdata/process_arch/htdocs.expected
+++ b/test/testdata/process_arch/htdocs.expected
@@ -1,5 +1,28 @@
-{'.': [],
- 'x86': ['.htaccess', 'packages.inc'],
+{'.': ['packages.inc'],
+ 'summary': ['arc.html',
+             'base-cygwin.html',
+             'corrupt.html',
+             'cygwin-debuginfo.html',
+             'cygwin-devel.html',
+             'cygwin.html',
+             'keychain.html',
+             'libdns_sd-devel.html',
+             'libdns_sd1.html',
+             'mDNSResponder.html',
+             'obs-a.html',
+             'obs-b.html',
+             'openssh.html',
+             'per-version-replacement-hint-only.html',
+             'per-version.html',
+             'perl-Net-SMTP-SSL.html',
+             'rpm-doc.html',
+             'staleversion.html',
+             'test-c.html',
+             'test-d.html',
+             'test-e.html',
+             'testpackage-subpackage.html',
+             'testpackage.html'],
+ 'x86': ['.htaccess'],
  'x86/arc': ['.htaccess', 'arc-4.32.7-10', 'arc-4.32.7-10-src'],
  'x86/base-cygwin': ['.htaccess', 'base-cygwin-3.6-1', 'base-cygwin-3.8-1'],
  'x86/corrupt': ['.htaccess', 'corrupt-2.0.0-1', 'corrupt-2.0.0-1-src'],
@@ -49,4 +72,15 @@
  'x86/test-d': ['.htaccess', 'test-d-1.0-1', 'test-d-1.0-1-src'],
  'x86/test-e': ['.htaccess', 'test-e-1.0-1', 'test-e-1.0-1-src'],
  'x86/testpackage': ['.htaccess', 'testpackage-1.0-1', 'testpackage-1.0-1-src'],
- 'x86/testpackage-subpackage': ['.htaccess', 'testpackage-subpackage-1.0-1']}
+ 'x86/testpackage-subpackage': ['.htaccess', 'testpackage-subpackage-1.0-1'],
+ 'x86_64': ['.htaccess'],
+ 'x86_64/obs-a': ['.htaccess', 'obs-a-1.0-1', 'obs-a-1.0-1-src'],
+ 'x86_64/obs-b': ['.htaccess', 'obs-b-1.0-1', 'obs-b-1.0-1-src'],
+ 'x86_64/perl-Net-SMTP-SSL': ['.htaccess',
+                              'perl-Net-SMTP-SSL-1.03-1',
+                              'perl-Net-SMTP-SSL-1.03-1-src',
+                              'perl-Net-SMTP-SSL-1.03-2',
+                              'perl-Net-SMTP-SSL-1.03-2-src'],
+ 'x86_64/test-c': ['.htaccess', 'test-c-1.0-1', 'test-c-1.0-1-src'],
+ 'x86_64/test-d': ['.htaccess', 'test-d-1.0-1', 'test-d-1.0-1-src'],
+ 'x86_64/test-e': ['.htaccess', 'test-e-1.0-1', 'test-e-1.0-1-src']}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.