summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--COPYING681
-rw-r--r--README.md9
-rw-r--r--indexer/Cargo.lock1933
-rw-r--r--indexer/Cargo.toml13
-rw-r--r--indexer/src/archive.rs19
-rw-r--r--indexer/src/archread.rs12
-rw-r--r--indexer/src/main.rs65
-rw-r--r--indexer/src/man.rs33
-rw-r--r--indexer/src/open.rs60
-rw-r--r--indexer/src/pkg.rs123
-rw-r--r--indexer/src/sys_alpine.rs99
-rw-r--r--indexer/src/sys_arch.rs48
-rw-r--r--indexer/src/sys_deb.rs12
-rw-r--r--indexer/src/sys_freebsd1.rs6
-rw-r--r--indexer/src/sys_freebsd2.rs8
-rw-r--r--indexer/src/sys_rpm.rs43
-rw-r--r--indexer/src/sys_rpmdir.rs6
-rw-r--r--lib/ManUtils/ManUtils.pm55
-rw-r--r--schema.sql121
-rw-r--r--sql/schema.sql281
-rw-r--r--sql/update-2016-10-02.sql30
-rw-r--r--sql/update-2016-10-03.sql4
-rw-r--r--sql/update-2016-10-06.sql3
-rw-r--r--sql/update-2016-10-09.sql7
-rw-r--r--sql/update-2016-10-16.sql19
-rw-r--r--sql/update-2016-11-06.sql2
-rw-r--r--sql/update-2016-12-18.sql26
-rwxr-xr-xutil/alpine.sh105
-rwxr-xr-xutil/arch.sh2
-rwxr-xr-xutil/centos.sh72
-rwxr-xr-xutil/cron.sh9
-rwxr-xr-xutil/debian.sh17
-rwxr-xr-xutil/fedora.sh49
-rwxr-xr-xutil/freebsd.sh77
-rwxr-xr-xutil/netbsd.sh346
-rwxr-xr-xutil/ubuntu.sh48
-rw-r--r--util/update_indices.sql12
-rw-r--r--web/Cargo.lock60
-rw-r--r--www/images/alpine.pngbin0 -> 903 bytes
-rw-r--r--www/images/gradients.pngbin183 -> 0 bytes
-rw-r--r--www/images/netbsd.pngbin0 -> 1300 bytes
-rw-r--r--www/images/search.pngbin1271 -> 0 bytes
-rwxr-xr-xwww/index.pl2080
-rw-r--r--www/man.css158
-rw-r--r--www/man.js23
46 files changed, 3553 insertions, 3224 deletions
diff --git a/.gitignore b/.gitignore
index a69b956..072394c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@
!/lib/ManUtils/ManUtils.xs
indexer/target
web/target
+util/.config
diff --git a/COPYING b/COPYING
index 251b5a4..dba13ed 100644
--- a/COPYING
+++ b/COPYING
@@ -1,20 +1,661 @@
-Copyright (c) 2012 Yoran Heling
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU Affero General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Remote Network Interaction; Use with the GNU General Public License.
+
+ Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<http://www.gnu.org/licenses/>.
diff --git a/README.md b/README.md
index 99d3164..0c2a007 100644
--- a/README.md
+++ b/README.md
@@ -9,15 +9,16 @@ Ironically, documentation about how things work is completely lacking.
- perl: A somewhat recent version (no idea which, due to my XS usage)
- postgresql: Also a somewhat recent version
-- rust + cargo (1.13+)
+- rust: Version who-knows-which
### Web front-end
-- DBI
+- AnyEvent
- DBD::Pg
-- TUWF
+- DBI
- JSON::XS
-- AnyEvent
+- SQL::Interp
+- TUWF
### Man page indexer
diff --git a/indexer/Cargo.lock b/indexer/Cargo.lock
index 7eada65..a614ac6 100644
--- a/indexer/Cargo.lock
+++ b/indexer/Cargo.lock
@@ -1,322 +1,177 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
-name = "adler32"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "aho-corasick"
-version = "0.7.3"
+version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
- "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr",
]
[[package]]
name = "ansi_term"
-version = "0.11.0"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi",
]
[[package]]
-name = "arrayref"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "arrayvec"
-version = "0.4.10"
+name = "async-trait"
+version = "0.1.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3"
dependencies = [
- "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
name = "atty"
-version = "0.2.11"
+version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hermit-abi",
+ "libc",
+ "winapi",
]
[[package]]
name = "autocfg"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "backtrace"
-version = "0.3.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "backtrace-sys"
-version = "0.1.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "base64"
-version = "0.6.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "base64"
-version = "0.10.1"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "bitflags"
-version = "1.0.4"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
-version = "0.3.3"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95"
dependencies = [
- "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "generic-array",
]
[[package]]
-name = "build_const"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "byte-tools"
-version = "0.2.0"
+name = "bumpalo"
+version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "byteorder"
-version = "1.3.1"
+version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
-version = "0.4.12"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]]
name = "cc"
-version = "1.0.37"
+version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]]
name = "cfg-if"
-version = "0.1.9"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "clap"
-version = "2.33.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "cloudabi"
-version = "0.0.3"
+version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc",
+ "num-integer",
+ "num-traits",
+ "time",
+ "winapi",
]
[[package]]
-name = "constant_time_eq"
-version = "0.1.3"
+name = "chunked_transfer"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
[[package]]
-name = "cookie"
-version = "0.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "cookie_store"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "core-foundation"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "core-foundation-sys"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "crc"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "crc32fast"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "crossbeam-deque"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "crossbeam-epoch"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "crossbeam-queue"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.6.5"
+name = "clap"
+version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
]
[[package]]
-name = "crypto-mac"
-version = "0.5.2"
+name = "cpufeatures"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
dependencies = [
- "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc",
]
[[package]]
-name = "derive_more"
-version = "0.14.0"
+name = "crypto-common"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567569e659735adb39ff2d4c20600f7cd78be5471f8c58ab162bce3c03fdbc5f"
dependencies = [
- "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "generic-array",
]
[[package]]
name = "digest"
-version = "0.7.6"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8549e6bfdecd113b7e221fe60b433087f6957387a20f8118ebca9b12af19143d"
dependencies = [
- "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "block-buffer",
+ "crypto-common",
+ "generic-array",
+ "subtle",
]
[[package]]
-name = "dtoa"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "either"
-version = "1.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "encoding"
version = "0.3.0-dev"
source = "git+https://github.com/lifthrasiir/rust-encoding#eb3d3c307df864f6a25e2ca16d49703e5d963ec5"
dependencies = [
- "encoding-index-japanese 1.20141219.6 (git+https://github.com/lifthrasiir/rust-encoding)",
- "encoding-index-korean 1.20141219.6 (git+https://github.com/lifthrasiir/rust-encoding)",
- "encoding-index-simpchinese 1.20160120.0 (git+https://github.com/lifthrasiir/rust-encoding)",
- "encoding-index-singlebyte 1.20160120.0 (git+https://github.com/lifthrasiir/rust-encoding)",
- "encoding-index-tradchinese 1.20141219.6 (git+https://github.com/lifthrasiir/rust-encoding)",
- "encoding-types 0.2.0 (git+https://github.com/lifthrasiir/rust-encoding)",
+ "encoding-index-japanese",
+ "encoding-index-korean",
+ "encoding-index-simpchinese",
+ "encoding-index-singlebyte",
+ "encoding-index-tradchinese",
+ "encoding-types",
]
[[package]]
@@ -324,7 +179,7 @@ name = "encoding-index-japanese"
version = "1.20141219.6"
source = "git+https://github.com/lifthrasiir/rust-encoding#eb3d3c307df864f6a25e2ca16d49703e5d963ec5"
dependencies = [
- "encoding_index_tests 0.1.5 (git+https://github.com/lifthrasiir/rust-encoding)",
+ "encoding_index_tests",
]
[[package]]
@@ -332,7 +187,7 @@ name = "encoding-index-korean"
version = "1.20141219.6"
source = "git+https://github.com/lifthrasiir/rust-encoding#eb3d3c307df864f6a25e2ca16d49703e5d963ec5"
dependencies = [
- "encoding_index_tests 0.1.5 (git+https://github.com/lifthrasiir/rust-encoding)",
+ "encoding_index_tests",
]
[[package]]
@@ -340,7 +195,7 @@ name = "encoding-index-simpchinese"
version = "1.20160120.0"
source = "git+https://github.com/lifthrasiir/rust-encoding#eb3d3c307df864f6a25e2ca16d49703e5d963ec5"
dependencies = [
- "encoding_index_tests 0.1.5 (git+https://github.com/lifthrasiir/rust-encoding)",
+ "encoding_index_tests",
]
[[package]]
@@ -348,7 +203,7 @@ name = "encoding-index-singlebyte"
version = "1.20160120.0"
source = "git+https://github.com/lifthrasiir/rust-encoding#eb3d3c307df864f6a25e2ca16d49703e5d963ec5"
dependencies = [
- "encoding_index_tests 0.1.5 (git+https://github.com/lifthrasiir/rust-encoding)",
+ "encoding_index_tests",
]
[[package]]
@@ -356,7 +211,7 @@ name = "encoding-index-tradchinese"
version = "1.20141219.6"
source = "git+https://github.com/lifthrasiir/rust-encoding#eb3d3c307df864f6a25e2ca16d49703e5d963ec5"
dependencies = [
- "encoding_index_tests 0.1.5 (git+https://github.com/lifthrasiir/rust-encoding)",
+ "encoding_index_tests",
]
[[package]]
@@ -370,1656 +225,954 @@ version = "0.1.5"
source = "git+https://github.com/lifthrasiir/rust-encoding#eb3d3c307df864f6a25e2ca16d49703e5d963ec5"
[[package]]
-name = "encoding_rs"
-version = "0.8.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "env_logger"
-version = "0.6.1"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
dependencies = [
- "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty",
+ "humantime",
+ "log",
+ "regex",
+ "termcolor",
]
[[package]]
-name = "error-chain"
-version = "0.12.1"
+name = "fallible-iterator"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
- "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
-name = "failure"
-version = "0.1.5"
+name = "form_urlencoded"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
dependencies = [
- "backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches",
+ "percent-encoding",
]
[[package]]
-name = "failure_derive"
-version = "0.1.5"
+name = "futures"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e"
dependencies = [
- "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
]
[[package]]
-name = "fake-simd"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "fallible-iterator"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "flate2"
-version = "1.0.7"
+name = "futures-channel"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27"
dependencies = [
- "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-core",
+ "futures-sink",
]
[[package]]
-name = "fnv"
-version = "1.0.6"
+name = "futures-core"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445"
[[package]]
-name = "foreign-types"
-version = "0.3.2"
+name = "futures-executor"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97"
dependencies = [
- "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-core",
+ "futures-task",
+ "futures-util",
]
[[package]]
-name = "foreign-types-shared"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "fuchsia-cprng"
-version = "0.1.1"
+name = "futures-io"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11"
[[package]]
-name = "fuchsia-zircon"
-version = "0.3.3"
+name = "futures-macro"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd"
dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
-name = "fuchsia-zircon-sys"
-version = "0.3.3"
+name = "futures-sink"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af"
[[package]]
-name = "futures"
-version = "0.1.27"
+name = "futures-task"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12"
[[package]]
-name = "futures-cpupool"
-version = "0.1.8"
+name = "futures-util"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e"
dependencies = [
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
]
[[package]]
name = "generic-array"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "h2"
-version = "0.1.20"
+version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
dependencies = [
- "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "typenum",
+ "version_check",
]
[[package]]
-name = "hex"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "hmac"
-version = "0.5.0"
+name = "getrandom"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
- "crypto-mac 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if",
+ "libc",
+ "wasi",
]
[[package]]
-name = "http"
-version = "0.1.17"
+name = "hermit-abi"
+version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc",
]
[[package]]
-name = "http-body"
-version = "0.1.0"
+name = "hmac"
+version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddca131f3e7f2ce2df364b57949a9d47915cfbd35e46cfee355ccebbf794d6a2"
dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "digest",
]
[[package]]
-name = "httparse"
-version = "1.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "humantime"
-version = "1.2.0"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "hyper"
-version = "0.12.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "h2 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "hyper-tls"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper 0.12.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "idna"
-version = "0.1.5"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
dependencies = [
- "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches",
+ "unicode-bidi",
+ "unicode-normalization",
]
[[package]]
name = "indexer"
version = "0.1.0"
dependencies = [
- "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "encoding 0.3.0-dev (git+https://github.com/lifthrasiir/rust-encoding)",
- "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libarchive3-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "postgres 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "quick-xml 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chrono",
+ "clap",
+ "encoding",
+ "env_logger",
+ "lazy_static",
+ "libarchive3-sys",
+ "libc",
+ "log",
+ "percent-encoding",
+ "postgres",
+ "quick-xml",
+ "regex",
+ "ring",
+ "ureq",
]
[[package]]
-name = "indexmap"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "iovec"
-version = "0.1.2"
+name = "instant"
+version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if",
]
[[package]]
-name = "itoa"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "kernel32-sys"
-version = "0.2.2"
+name = "js-sys"
+version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasm-bindgen",
]
[[package]]
name = "lazy_static"
-version = "1.3.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libarchive3-sys"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3cd3beae8f59a4c7a806523269b5392037577c150446e88d684dfa6de6031ca7"
dependencies = [
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc",
+ "pkg-config",
]
[[package]]
name = "libc"
-version = "0.2.55"
+version = "0.2.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01"
[[package]]
name = "lock_api"
-version = "0.1.5"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
dependencies = [
- "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scopeguard",
]
[[package]]
name = "log"
-version = "0.4.6"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if",
]
[[package]]
name = "matches"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "md5"
-version = "0.3.8"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
-name = "memchr"
-version = "1.0.2"
+name = "md-5"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6a38fc55c8bbc10058782919516f88826e70320db6d206aebc49611d24216ae"
dependencies = [
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
+ "digest",
]
[[package]]
name = "memchr"
-version = "2.2.0"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "memoffset"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "mime"
-version = "0.3.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "mime_guess"
-version = "2.0.0-alpha.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "miniz_oxide"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "miniz_oxide_c_api"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "mio"
-version = "0.6.18"
+version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
dependencies = [
- "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc",
+ "log",
+ "miow",
+ "ntapi",
+ "winapi",
]
[[package]]
name = "miow"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "native-tls"
-version = "0.2.3"
+version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
dependencies = [
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)",
- "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi",
]
[[package]]
-name = "net2"
-version = "0.2.33"
+name = "ntapi"
+version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
dependencies = [
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi",
]
[[package]]
-name = "nodrop"
-version = "0.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "num-integer"
-version = "0.1.41"
+version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
- "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg",
+ "num-traits",
]
[[package]]
name = "num-traits"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "num_cpus"
-version = "1.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "numtoa"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "openssl"
-version = "0.10.23"
+version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg",
]
[[package]]
-name = "openssl-probe"
-version = "0.1.2"
+name = "once_cell"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "openssl-sys"
-version = "0.9.47"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "owning_ref"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "parking_lot"
-version = "0.7.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
- "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "instant",
+ "lock_api",
+ "parking_lot_core",
]
[[package]]
name = "parking_lot_core"
-version = "0.4.0"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
dependencies = [
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi",
]
[[package]]
name = "percent-encoding"
-version = "1.0.1"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "phf"
-version = "0.7.24"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9fc3db1018c4b59d7d582a739436478b6035138b6aecbce989fc91c3e98409f"
dependencies = [
- "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_shared",
]
[[package]]
-name = "phf_codegen"
-version = "0.7.24"
+name = "phf_shared"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
dependencies = [
- "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "siphasher",
]
[[package]]
-name = "phf_generator"
-version = "0.7.24"
+name = "pin-project-lite"
+version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
[[package]]
-name = "phf_shared"
-version = "0.7.24"
+name = "pin-utils"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
-version = "0.3.14"
+version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
[[package]]
name = "postgres"
-version = "0.15.2"
+version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb76d6535496f633fa799bb872ffb4790e9cbdedda9d35564ca0252f930c0dd5"
dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "fallible-iterator 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "postgres-protocol 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "postgres-shared 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes",
+ "fallible-iterator",
+ "futures",
+ "log",
+ "tokio",
+ "tokio-postgres",
]
[[package]]
name = "postgres-protocol"
-version = "0.3.2"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79ec03bce71f18b4a27c4c64c6ba2ddf74686d69b91d8714fb32ead3adaed713"
dependencies = [
- "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "fallible-iterator 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "hmac 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "md5 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "stringprep 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "base64",
+ "byteorder",
+ "bytes",
+ "fallible-iterator",
+ "hmac",
+ "md-5",
+ "memchr",
+ "rand",
+ "sha2",
+ "stringprep",
]
[[package]]
-name = "postgres-shared"
-version = "0.4.2"
+name = "postgres-types"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04619f94ba0cc80999f4fc7073607cb825bc739a883cb6d20900fc5e009d6b0d"
dependencies = [
- "fallible-iterator 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "postgres-protocol 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes",
+ "fallible-iterator",
+ "postgres-protocol",
]
[[package]]
-name = "proc-macro2"
-version = "0.4.30"
+name = "ppv-lite86"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
[[package]]
-name = "publicsuffix"
-version = "1.5.2"
+name = "proc-macro2"
+version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb37d2df5df740e582f28f8560cf425f52bb267d872fe58358eadb554909f07a"
dependencies = [
- "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid",
]
[[package]]
-name = "quick-error"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "quick-xml"
-version = "0.14.0"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b"
dependencies = [
- "derive_more 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr",
]
[[package]]
name = "quote"
-version = "0.6.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rand"
-version = "0.3.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rand"
-version = "0.4.6"
+version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
dependencies = [
- "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2",
]
[[package]]
name = "rand"
-version = "0.6.5"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
- "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
]
[[package]]
name = "rand_chacha"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
- "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ppv-lite86",
+ "rand_core",
]
[[package]]
name = "rand_core"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "rand_hc"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rand_isaac"
-version = "0.1.1"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getrandom",
]
[[package]]
-name = "rand_jitter"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rand_os"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rand_pcg"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rand_xorshift"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rdrand"
-version = "0.4.0"
+name = "rand_hc"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core",
]
[[package]]
name = "redox_syscall"
-version = "0.1.54"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "redox_termios"
-version = "0.1.1"
+version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
- "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags",
]
[[package]]
name = "regex"
-version = "1.1.6"
+version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
- "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
]
[[package]]
name = "regex-syntax"
-version = "0.6.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "remove_dir_all"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "reqwest"
-version = "0.9.17"
+version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper 0.12.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "ring"
-version = "0.14.6"
+version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
- "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc",
+ "libc",
+ "once_cell",
+ "spin",
+ "untrusted",
+ "web-sys",
+ "winapi",
]
[[package]]
-name = "rustc-demangle"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "ryu"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "safemem"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "schannel"
-version = "0.1.15"
+name = "rustls"
+version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84"
dependencies = [
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log",
+ "ring",
+ "sct",
+ "webpki",
]
[[package]]
name = "scopeguard"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "security-framework"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "security-framework-sys"
-version = "0.3.1"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
-name = "semver"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "semver-parser"
+name = "sct"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "serde"
-version = "1.0.91"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.91"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.39"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "serde_urlencoded"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
dependencies = [
- "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring",
+ "untrusted",
]
[[package]]
name = "sha2"
-version = "0.7.1"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "900d964dd36bb15bcf2f2b35694c072feab74969a54f2bbeec7a2d725d2bdcb6"
dependencies = [
- "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if",
+ "cpufeatures",
+ "digest",
]
[[package]]
name = "siphasher"
-version = "0.2.3"
+version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b"
[[package]]
name = "slab"
-version = "0.4.2"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
[[package]]
name = "smallvec"
-version = "0.6.9"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "socket2"
-version = "0.3.9"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516"
dependencies = [
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc",
+ "winapi",
]
[[package]]
name = "spin"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "stable_deref_trait"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "string"
-version = "0.1.3"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "stringprep"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1"
dependencies = [
- "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-bidi",
+ "unicode-normalization",
]
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
-name = "syn"
-version = "0.15.34"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.10.2"
+name = "subtle"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
-name = "tempfile"
-version = "3.0.8"
+name = "syn"
+version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
dependencies = [
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
]
[[package]]
name = "termcolor"
-version = "1.0.4"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
- "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-util",
]
[[package]]
-name = "termion"
-version = "1.5.2"
+name = "textwrap"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width",
]
[[package]]
-name = "textwrap"
-version = "0.11.0"
+name = "time"
+version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
dependencies = [
- "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc",
+ "winapi",
]
[[package]]
-name = "thread_local"
-version = "0.3.6"
+name = "tinyvec"
+version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
dependencies = [
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tinyvec_macros",
]
[[package]]
-name = "time"
-version = "0.1.42"
+name = "tinyvec_macros"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
-version = "0.1.20"
+version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144"
dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg",
+ "bytes",
+ "libc",
+ "memchr",
+ "mio",
+ "pin-project-lite",
+ "winapi",
]
[[package]]
-name = "tokio-buf"
-version = "0.1.1"
+name = "tokio-postgres"
+version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b6c8b33df661b548dcd8f9bf87debb8c56c05657ed291122e1188698c2ece95"
dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "async-trait",
+ "byteorder",
+ "bytes",
+ "fallible-iterator",
+ "futures",
+ "log",
+ "parking_lot",
+ "percent-encoding",
+ "phf",
+ "pin-project-lite",
+ "postgres-protocol",
+ "postgres-types",
+ "socket2",
+ "tokio",
+ "tokio-util",
]
[[package]]
-name = "tokio-current-thread"
-version = "0.1.6"
+name = "tokio-util"
+version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
dependencies = [
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
]
[[package]]
-name = "tokio-executor"
-version = "0.1.7"
+name = "typenum"
+version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec"
[[package]]
-name = "tokio-io"
-version = "0.1.12"
+name = "unicode-bidi"
+version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
[[package]]
-name = "tokio-reactor"
-version = "0.1.9"
+name = "unicode-normalization"
+version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
dependencies = [
- "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tinyvec",
]
[[package]]
-name = "tokio-sync"
-version = "0.1.5"
+name = "unicode-width"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
-name = "tokio-tcp"
-version = "0.1.3"
+name = "unicode-xid"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
-name = "tokio-threadpool"
-version = "0.1.14"
+name = "untrusted"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
-name = "tokio-timer"
-version = "0.2.11"
+name = "ureq"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c5c448dcb78ec38c7d59ec61f87f70a98ea19171e06c139357e012ee226fec90"
dependencies = [
- "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "base64",
+ "chunked_transfer",
+ "log",
+ "once_cell",
+ "rustls",
+ "url",
+ "webpki",
+ "webpki-roots",
]
[[package]]
-name = "tokio-trace-core"
-version = "0.1.0"
+name = "url"
+version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
dependencies = [
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "form_urlencoded",
+ "idna",
+ "matches",
+ "percent-encoding",
]
[[package]]
-name = "try-lock"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "try_from"
-version = "0.3.2"
+name = "vec_map"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
-]
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
-name = "typenum"
-version = "1.10.0"
+name = "version_check"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
-name = "ucd-util"
-version = "0.1.3"
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
-name = "unicase"
-version = "1.4.2"
+name = "wasm-bindgen"
+version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
dependencies = [
- "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if",
+ "wasm-bindgen-macro",
]
[[package]]
-name = "unicase"
-version = "2.4.0"
+name = "wasm-bindgen-backend"
+version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
dependencies = [
- "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bumpalo",
+ "lazy_static",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
]
[[package]]
-name = "unicode-bidi"
-version = "0.3.4"
+name = "wasm-bindgen-macro"
+version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
dependencies = [
- "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote",
+ "wasm-bindgen-macro-support",
]
[[package]]
-name = "unicode-normalization"
-version = "0.1.8"
+name = "wasm-bindgen-macro-support"
+version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
dependencies = [
- "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
]
[[package]]
-name = "unicode-width"
-version = "0.1.5"
+name = "wasm-bindgen-shared"
+version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
[[package]]
-name = "unicode-xid"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "untrusted"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "url"
-version = "1.7.2"
+name = "web-sys"
+version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
dependencies = [
- "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "js-sys",
+ "wasm-bindgen",
]
[[package]]
-name = "utf8-ranges"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "uuid"
-version = "0.7.4"
+name = "webpki"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
dependencies = [
- "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring",
+ "untrusted",
]
[[package]]
-name = "vcpkg"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "vec_map"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "version_check"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "want"
-version = "0.0.6"
+name = "webpki-roots"
+version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c475786c6f47219345717a043a37ec04cb4bc185e28853adcc4fa0a947eba630"
dependencies = [
- "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki",
]
[[package]]
name = "winapi"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "winapi"
-version = "0.3.7"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
- "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
]
[[package]]
-name = "winapi-build"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
-version = "0.1.2"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "wincolor"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "ws2_32-sys"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[metadata]
-"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
-"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c"
-"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
-"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
-"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
-"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
-"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf"
-"checksum backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)" = "1a13fc43f04daf08ab4f71e3d27e1fc27fc437d3e95ac0063a796d92fb40f39b"
-"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
-"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
-"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9"
-"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
-"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
-"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
-"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
-"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
-"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
-"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d"
-"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
-"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
-"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
-"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
-"checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5"
-"checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c"
-"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
-"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
-"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
-"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
-"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
-"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4"
-"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
-"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
-"checksum crypto-mac 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0999b4ff4d3446d4ddb19a63e9e00c1876e75cd7000d20e57a693b4b3f08d958"
-"checksum derive_more 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fbe9f11be34f800b3ecaaed0ec9ec2e015d1d0ba0c8644c1310f73d6e8994615"
-"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
-"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e"
-"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
-"checksum encoding 0.3.0-dev (git+https://github.com/lifthrasiir/rust-encoding)" = "<none>"
-"checksum encoding-index-japanese 1.20141219.6 (git+https://github.com/lifthrasiir/rust-encoding)" = "<none>"
-"checksum encoding-index-korean 1.20141219.6 (git+https://github.com/lifthrasiir/rust-encoding)" = "<none>"
-"checksum encoding-index-simpchinese 1.20160120.0 (git+https://github.com/lifthrasiir/rust-encoding)" = "<none>"
-"checksum encoding-index-singlebyte 1.20160120.0 (git+https://github.com/lifthrasiir/rust-encoding)" = "<none>"
-"checksum encoding-index-tradchinese 1.20141219.6 (git+https://github.com/lifthrasiir/rust-encoding)" = "<none>"
-"checksum encoding-types 0.2.0 (git+https://github.com/lifthrasiir/rust-encoding)" = "<none>"
-"checksum encoding_index_tests 0.1.5 (git+https://github.com/lifthrasiir/rust-encoding)" = "<none>"
-"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed"
-"checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a"
-"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9"
-"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
-"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
-"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
-"checksum fallible-iterator 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eb7217124812dc5672b7476d0c2d20cfe9f7c0f1ba0904b674a9762a0212f72e"
-"checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa"
-"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
-"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
-"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
-"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
-"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
-"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
-"checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139"
-"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
-"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
-"checksum h2 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "2b53def7bb0253af7718036fe9338c15defd209136819464384f3a553e07481b"
-"checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa"
-"checksum hmac 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44f3bdb08579d99d7dc761c0e266f13b5f2ab8c8c703b9fc9ef333cd8f48f55e"
-"checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a"
-"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d"
-"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83"
-"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
-"checksum hyper 0.12.29 (registry+https://github.com/rust-lang/crates.io-index)" = "e2cd6adf83b3347d36e271f030621a8cf95fd1fd0760546b9fc5a24a0f1447c7"
-"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f"
-"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
-"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
-"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
-"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
-"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
-"checksum libarchive3-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3cd3beae8f59a4c7a806523269b5392037577c150446e88d684dfa6de6031ca7"
-"checksum libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "42914d39aad277d9e176efbdad68acb1d5443ab65afe0e0e4f0d49352a950880"
-"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
-"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
-"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
-"checksum md5 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "79c56d6a0b07f9e19282511c83fc5b086364cbae4ba8c7d5f190c3d9b0425a48"
-"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
-"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
-"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
-"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425"
-"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed"
-"checksum miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c468f2369f07d651a5d0bb2c9079f8488a66d5466efe42d0c5c6466edcb7f71e"
-"checksum miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fe927a42e3807ef71defb191dc87d4e24479b221e67015fe38ae2b7b447bab"
-"checksum mio 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "9fbe95ae9216d99c944a1afa429fef2a2ed012b65b0840de5047a86a82969502"
-"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
-"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e"
-"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
-"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
-"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
-"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
-"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
-"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
-"checksum openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)" = "97c140cbb82f3b3468193dd14c1b88def39f341f68257f8a7fe8ed9ed3f628a5"
-"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
-"checksum openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)" = "75bdd6dbbb4958d38e47a1d2348847ad1eb4dc205dc5d37473ae504391865acc"
-"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
-"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
-"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
-"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
-"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
-"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e"
-"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
-"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
-"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
-"checksum postgres 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "115dde90ef51af573580c035857badbece2aa5cde3de1dfb3c932969ca92a6c5"
-"checksum postgres-protocol 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2487e66455bf88a1b247bf08a3ce7fe5197ac6d67228d920b0ee6a0e97fd7312"
-"checksum postgres-shared 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ffac35b3e0029b404c24a3b82149b4e904f293e8ca4a327eefa24d3ca50df36f"
-"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
-"checksum publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5afecba86dcf1e4fd610246f89899d1924fe12e1e89f555eb7c7f710f3c5ad1d"
-"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
-"checksum quick-xml 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a8b2062cd4735d683121dbd525f5961226936229b0ac6bbbc40b34155744a41"
-"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
-"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
-"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
-"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
-"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
-"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
-"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
-"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
-"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
-"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
-"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
-"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
-"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
-"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
-"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252"
-"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
-"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58"
-"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
-"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
-"checksum reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e57803405f8ea0eb041c1567dac36127e0c8caa1251c843cb03d43fd767b3d50"
-"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c"
-"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288"
-"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f"
-"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
-"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339"
-"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
-"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2"
-"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56"
-"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
-"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-"checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd"
-"checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f"
-"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d"
-"checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a"
-"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0"
-"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
-"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
-"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be"
-"checksum socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "4e626972d3593207547f14bf5fc9efa4d0e7283deb73fef1dff313dae9ab8878"
-"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55"
-"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
-"checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b"
-"checksum stringprep 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1"
-"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
-"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe"
-"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
-"checksum tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef"
-"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
-"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea"
-"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
-"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
-"checksum tokio 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "94a1f9396aec29d31bb16c24d155cfa144d1af91c40740125db3131bdaf76da8"
-"checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46"
-"checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443"
-"checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e"
-"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926"
-"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce"
-"checksum tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2f843ffdf8d6e1f90bddd48da43f99ab071660cd92b7ec560ef3cdfd7a409a"
-"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119"
-"checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2"
-"checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e"
-"checksum tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "350c9edade9830dc185ae48ba45667a445ab59f6167ef6d0254ec9d2430d9dd3"
-"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
-"checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b"
-"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
-"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
-"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
-"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6"
-"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
-"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426"
-"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
-"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
-"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
-"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
-"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
-"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
-"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d"
-"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
-"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
-"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
-"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
-"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
-"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
-"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
-"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
-"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/indexer/Cargo.toml b/indexer/Cargo.toml
index 6d952cb..271da67 100644
--- a/indexer/Cargo.toml
+++ b/indexer/Cargo.toml
@@ -2,19 +2,20 @@
name = "indexer"
version = "0.1.0"
authors = ["Yorhel <git@yorhel.nl>"]
+edition = "2018"
[dependencies]
regex = "1.1.0"
log = "0.4.1"
-env_logger = "0.6.0"
+env_logger = "0.9.0"
lazy_static = "1.0.0"
libc = "0.2.39"
libarchive3-sys = "0.1.2"
encoding = { git = "https://github.com/lifthrasiir/rust-encoding", features = ["no-optimized-legacy-encoding"] }
-ring = "0.14.6"
-postgres = "0.15.2"
+ring = "0.16.20"
+postgres = "0.19.0"
clap = "2.31.2"
-reqwest = "0.9.17"
-url = "1.7.0"
+ureq = "2.3.1"
+percent-encoding = "2.0"
chrono = "0.4.0"
-quick-xml = "0.14.0"
+quick-xml = "0.22.0"
diff --git a/indexer/src/archive.rs b/indexer/src/archive.rs
index 57c8305..75aba3b 100644
--- a/indexer/src/archive.rs
+++ b/indexer/src/archive.rs
@@ -1,6 +1,5 @@
use std::str;
use std::ptr;
-use std::error::Error as ErrorTrait;
use std::io::{Result,Error,Read};
use std::ffi::{CStr,CString};
@@ -23,7 +22,7 @@ use libarchive3_sys::ffi;
pub struct Archive<'a> {
a: *mut ffi::Struct_archive,
- rd: &'a mut Read,
+ rd: &'a mut dyn Read,
buf: Vec<u8>,
err: Option<Error>,
eof: bool,
@@ -61,7 +60,7 @@ unsafe extern "C" fn archive_read_cb(_: *mut ffi::Struct_archive, data: *mut c_v
match arch.rd.read(&mut arch.buf[..]) {
Ok(s) => s as ssize_t,
Err(e) => {
- let desc = CString::new(e.description()).unwrap();
+ let desc = CString::new(e.to_string()).unwrap();
let fmt = CString::new("%s").unwrap();
ffi::archive_set_error(arch.a, e.raw_os_error().unwrap_or(0), fmt.as_ptr(), desc.as_ptr());
arch.err = Some(e);
@@ -72,7 +71,7 @@ unsafe extern "C" fn archive_read_cb(_: *mut ffi::Struct_archive, data: *mut c_v
impl<'a> Archive<'a> {
- fn new(rd: &mut Read, a: *mut ffi::Struct_archive) -> Result<Box<Archive>> {
+ fn new(rd: &mut dyn Read, a: *mut ffi::Struct_archive) -> Result<Box<Archive>> {
let bufsize = 64*1024;
let mut buf = Vec::with_capacity(bufsize);
unsafe { buf.set_len(bufsize) };
@@ -131,17 +130,17 @@ impl<'a> Archive<'a> {
}
}
- pub fn open_archive(rd: &mut Read) -> Result<Option<ArchiveEntry>> {
+ pub fn open_archive(rd: &mut dyn Read) -> Result<Option<ArchiveEntry>> {
let a = unsafe {
let a = ffi::archive_read_new();
ffi::archive_read_support_filter_all(a);
ffi::archive_read_support_format_all(a);
a
};
- try!(Self::new(rd, a)).entry()
+ Self::new(rd, a)?.entry()
}
- pub fn open_raw(rd: &mut Read) -> Result<RawEntry> {
+ pub fn open_raw(rd: &mut dyn Read) -> Result<RawEntry> {
let a = unsafe {
let a = ffi::archive_read_new();
ffi::archive_read_support_filter_all(a);
@@ -149,7 +148,7 @@ impl<'a> Archive<'a> {
ffi::archive_read_support_format_empty(a);
a
};
- let mut a = try!(Self::new(rd, a));
+ let mut a = Self::new(rd, a)?;
let mut e: *mut ffi::Struct_archive_entry = ptr::null_mut();
let res = unsafe { ffi::archive_read_next_header(a.a, &mut e) };
match res {
@@ -282,10 +281,10 @@ pub fn walk<F>(ent: Option<ArchiveEntry>, mut cb: F) -> Result<()>
{
let mut ent = ent;
while let Some(mut e) = ent {
- if !try!(cb(&mut e)) {
+ if !cb(&mut e)? {
break;
}
- ent = try!(e.next());
+ ent = e.next()?;
}
Ok(())
}
diff --git a/indexer/src/archread.rs b/indexer/src/archread.rs
index d9c71f3..146ce79 100644
--- a/indexer/src/archread.rs
+++ b/indexer/src/archread.rs
@@ -1,7 +1,7 @@
use std::io::Result;
use std::collections::HashMap;
-use archive::{walk,ArchiveEntry,FileType};
+use crate::archive::{walk,ArchiveEntry,FileType};
/* I had hoped that reading man pages from an archive would just be a simple:
*
@@ -121,7 +121,7 @@ impl FileList {
links: Vec::new(),
};
- try!(walk(ent, |mut e| {
+ walk(ent, |mut e| {
let path = match e.path() {
Some(x) => x.to_string(),
None => { warn!("Invalid UTF-8 filename in archive"); return Ok(true) }
@@ -144,7 +144,7 @@ impl FileList {
EntryType::Hardlink
} else if interest_cb(&path) {
let pathv = [&path as &str];
- try!(file_cb(&pathv[..], &mut e));
+ file_cb(&pathv[..], &mut e)?;
EntryType::Handled
} else {
EntryType::Regular
@@ -157,7 +157,7 @@ impl FileList {
let opath = ocomp.join("/");
if interest_cb(&opath) {
let pathv = [&opath as &str];
- try!(file_cb(&pathv[..], &mut e));
+ file_cb(&pathv[..], &mut e)?;
*fl.seen.get_mut(&opath).unwrap() = EntryType::Handled;
}
}
@@ -173,7 +173,7 @@ impl FileList {
fl.seen.insert(path, et);
Ok(true)
- }));
+ })?;
Ok(fl)
}
@@ -301,7 +301,7 @@ impl MissedFiles {
walk(ent, |mut e| {
if let Some(f) = e.path().and_then(|p| self.0.remove(p)) {
let v: Vec<&str> = f.iter().map(|x| x as &str).collect();
- try!(file_cb(&v, &mut e))
+ file_cb(&v, &mut e)?
}
Ok(self.0.len() > 0)
})
diff --git a/indexer/src/main.rs b/indexer/src/main.rs
index 2373723..f8c1933 100644
--- a/indexer/src/main.rs
+++ b/indexer/src/main.rs
@@ -1,23 +1,13 @@
#[macro_use] extern crate log;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate clap;
-extern crate env_logger;
-extern crate regex;
-extern crate libarchive3_sys;
-extern crate libc;
-extern crate ring;
-extern crate encoding;
-extern crate postgres;
-extern crate reqwest;
-extern crate url;
-extern crate chrono;
-extern crate quick_xml;
mod archive;
mod archread;
mod man;
mod open;
mod pkg;
+mod sys_alpine;
mod sys_arch;
mod sys_deb;
mod sys_freebsd1;
@@ -27,12 +17,12 @@ mod sys_rpm;
// Convenience function to get a system id by short-name. Panics if the system doesn't exist.
-fn sysbyshort(conn: &postgres::GenericConnection, short: &str) -> i32 {
- let r = conn.query("SELECT id FROM systems WHERE short = $1", &[&short]).unwrap();
- if r.is_empty() {
+fn sysbyshort<T>(conn: &mut T, short: &str) -> i32 where T: postgres::GenericClient {
+ if let Some(r) = conn.query_opt("SELECT id FROM systems WHERE short = $1", &[&short]).unwrap() {
+ return r.get(0);
+ } else {
panic!("Invalid system: {}", short);
}
- r.get(0).get(0)
}
@@ -52,6 +42,12 @@ fn main() {
(@arg arch: --arch +takes_value "Architecture")
(@arg FILE: +required "Package file")
)
+ (@subcommand alpine =>
+ (about: "Index an Alpine Linux repository")
+ (@arg sys: --sys +required +takes_value "System short-name")
+ (@arg mirror: --mirror +required +takes_value "Mirror URL")
+ (@arg repo: --repo +required +takes_value "Repository name")
+ )
(@subcommand arch =>
(about: "Index an Arch Linux repository")
(@arg sys: --sys +required +takes_value "System short-name")
@@ -112,7 +108,7 @@ fn main() {
Ok(x) => x,
Err(_) => { error!("MANNED_PG not set."); return }
};
- let db = match postgres::Connection::connect(&dbhost[..], postgres::TlsMode::None) {
+ let mut db = match postgres::Client::connect(&dbhost[..], postgres::tls::NoTls) {
Ok(x) => x,
Err(x) => { error!("Can't connect to postgres: {}", x); return },
};
@@ -125,9 +121,10 @@ fn main() {
"max" => pkg::Date::Max,
s => pkg::Date::Known(s),
};
- pkg::pkg(&db, pkg::PkgOpt {
+ let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
+ pkg::pkg(&mut db, pkg::PkgOpt {
force: matches.is_present("force"),
- sys: sysbyshort(&db, matches.value_of("sys").unwrap()),
+ sys: sys,
cat: matches.value_of("cat").unwrap(),
pkg: matches.value_of("pkg").unwrap(),
ver: matches.value_of("ver").unwrap(),
@@ -137,17 +134,25 @@ fn main() {
});
}
+ if let Some(matches) = arg.subcommand_matches("alpine") {
+ let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
+ sys_alpine::sync(&mut db, sys,
+ matches.value_of("mirror").unwrap(),
+ matches.value_of("repo").unwrap()
+ );
+ }
+
if let Some(matches) = arg.subcommand_matches("arch") {
- sys_arch::sync(&db,
- sysbyshort(&db, matches.value_of("sys").unwrap()),
+ let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
+ sys_arch::sync(&mut db, sys,
matches.value_of("mirror").unwrap(),
matches.value_of("repo").unwrap()
);
}
if let Some(matches) = arg.subcommand_matches("deb") {
- sys_deb::sync(&db,
- sysbyshort(&db, matches.value_of("sys").unwrap()),
+ let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
+ sys_deb::sync(&mut db, sys,
matches.value_of("mirror").unwrap(),
matches.value_of("contents").map(|e| { open::Path{ path: e, cache: true, canbelocal: true} }),
open::Path{ path: matches.value_of("packages").unwrap(), cache: true, canbelocal: true},
@@ -155,31 +160,31 @@ fn main() {
}
if let Some(matches) = arg.subcommand_matches("freebsd1") {
- sys_freebsd1::sync(&db,
- sysbyshort(&db, matches.value_of("sys").unwrap()),
+ let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
+ sys_freebsd1::sync(&mut db, sys,
matches.value_of("arch").unwrap(),
matches.value_of("mirror").unwrap()
).unwrap_or_else(|e| error!("{}", e));
}
if let Some(matches) = arg.subcommand_matches("freebsd2") {
- sys_freebsd2::sync(&db,
- sysbyshort(&db, matches.value_of("sys").unwrap()),
+ let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
+ sys_freebsd2::sync(&mut db, sys,
matches.value_of("mirror").unwrap()
).unwrap_or_else(|e| error!("{}", e));
}
if let Some(matches) = arg.subcommand_matches("rpmdir") {
- sys_rpmdir::sync(&db,
- sysbyshort(&db, matches.value_of("sys").unwrap()),
+ let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
+ sys_rpmdir::sync(&mut db, sys,
matches.value_of("cat").unwrap(),
matches.value_of("mirror").unwrap()
).unwrap_or_else(|e| error!("{}", e));
}
if let Some(matches) = arg.subcommand_matches("rpm") {
- sys_rpm::sync(&db,
- sysbyshort(&db, matches.value_of("sys").unwrap()),
+ let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
+ sys_rpm::sync(&mut db, sys,
matches.value_of("cat").unwrap(),
matches.value_of("mirror").unwrap()
).unwrap_or_else(|e| error!("{}", e));
diff --git a/indexer/src/man.rs b/indexer/src/man.rs
index 32805ae..d594d81 100644
--- a/indexer/src/man.rs
+++ b/indexer/src/man.rs
@@ -8,7 +8,7 @@ use encoding::{all,EncodingRef};
use encoding::label::encoding_from_whatwg_label;
use ring::digest;
-use archive::Archive;
+use crate::archive::Archive;
// Anything larger than this just isn't a man page. I hope.
const MAX_MAN_SIZE: u64 = 20*1024*1024;
@@ -27,29 +27,39 @@ pub fn parse_path(path: &str) -> Option<(&str, &str, &str)> {
/man[a-z0-9]/ # Subdir
([^/]+?) # Man page name (non-greedy)
\. ([^/\.]+) # Section
- (?: \. (?: gz|lzma|bz2|xz ))* $ # Any number of compression extensions
+ (?: \. (?: gz|lzma|bz2|xz|zst ))* $ # Any number of compression extensions
").unwrap();
}
let cap = match RE.captures(path) { Some(x) => x, None => return None };
- let locale = cap.get(1).map(|e| e.as_str()).unwrap_or("");
+ let mut locale = cap.get(1).map(|e| e.as_str()).unwrap_or("");
let name = cap.get(2).unwrap().as_str();
let section = cap.get(3).unwrap().as_str();
+ // Some weird directories that happen to match the locale
+ if locale.contains("openmpi") || locale.contains("mpich") || locale.contains("mvapich") {
+ locale = "";
+ }
+
// Not everything matching the regex is necessarily a man page, exclude some special cases.
match (name, section, locale) {
// Files that totally aren't man pages
("Makefile", "am", _) |
(".cvsignore", _, _) |
(_, "in", _) |
- (_, "gz", _) |
+ (_, "orig", _) |
+ (_, "pdf", _) |
+ (_, "md", _) |
(_, "lzma", _) |
+ (_, "gz", _) |
+ (_, "gzip", _) |
(_, "bz2", _) |
(_, "xz", _) |
(_, "html", _) => None,
- // Some weird directories that happen to match the locale
+ // Some more weird directories that happen to match the locale
(n, s, "5man") |
(n, s, "c") |
+ (n, s, "man") |
(n, s, "man1") |
(n, s, "man2") |
(n, s, "man3") |
@@ -59,7 +69,8 @@ pub fn parse_path(path: &str) -> Option<(&str, &str, &str)> {
(n, s, "man7") |
(n, s, "man8") |
(n, s, "Man-Part1") |
- (n, s, "Man-Part2") => Some((n, s, "")),
+ (n, s, "Man-Part2") |
+ (n, s, "overrides") => Some((n, s, "")),
// Nothing special!
x => Some(x)
}
@@ -195,16 +206,16 @@ fn codec_from_path(path: &str) -> Option<EncodingRef> {
// Decompresses / decodes a man page and returns its SHA-1 hash, encoding name, and UTF-8 contents.
-pub fn decode(paths: &[&str], ent: &mut Read) -> io::Result<(digest::Digest,&'static str,String)> {
- let mut decomp = try!(Archive::open_raw(ent)).take(MAX_MAN_SIZE+1);
+pub fn decode(paths: &[&str], ent: &mut dyn Read) -> io::Result<(digest::Digest,&'static str,String)> {
+ let mut decomp = Archive::open_raw(ent)?.take(MAX_MAN_SIZE+1);
let mut data = Vec::new();
- try!(decomp.read_to_end(&mut data));
+ decomp.read_to_end(&mut data)?;
if let Some(e) = validate(&data) {
return Err(io::Error::new(io::ErrorKind::InvalidData, e));
}
- let dig = digest::digest(&digest::SHA1, &data);
+ let dig = digest::digest(&digest::SHA1_FOR_LEGACY_USE_ONLY, &data);
// Create a list of encodings to try, starting with UTF-8
let mut encs : Vec<EncodingRef> = vec![all::UTF_8];
@@ -301,6 +312,6 @@ fn test_decode_zh() {
assert_eq!(dig.as_ref(), &filehash[..]);
assert_eq!(enc, "gbk");
- let utf8dig = digest::digest(&digest::SHA1, s.as_bytes());
+ let utf8dig = digest::digest(&digest::SHA1_FOR_LEGACY_USE_ONLY, s.as_bytes());
assert_eq!(utf8dig.as_ref(), &utf8hash[..]);
}
diff --git a/indexer/src/open.rs b/indexer/src/open.rs
index 9ecdfa4..9375d5a 100644
--- a/indexer/src/open.rs
+++ b/indexer/src/open.rs
@@ -3,9 +3,8 @@ use std::fs::{File,create_dir_all,metadata,read_dir,remove_file};
use std::time::{Duration,SystemTime};
use regex::bytes::Regex;
use ring::digest;
-use url::Url;
-use url::percent_encoding::percent_decode;
-use reqwest;
+use percent_encoding::percent_decode;
+use ureq;
const CACHE_PATH: &'static str = "/var/tmp/manned-indexer";
@@ -20,34 +19,20 @@ pub struct Path<'a> {
}
-fn cache_fn(url: &Url) -> String {
- let name = url.path_segments().unwrap().last().unwrap();
- let name = if name == "" { "index" } else { name };
-
- let hash = digest::digest(&digest::SHA1, url.as_str().as_bytes())
- .as_ref()[0..8].into_iter()
- .fold(0u64, |a, &e| (a<<8) + e as u64);
-
- format!("{}/{}-{}-{:x}", CACHE_PATH, url.host_str().unwrap(), name, hash)
-}
-
-
-fn fetch(url: &str) -> Result<Box<Read>> {
- let res = try!(reqwest::Client::new()
- .get(url)
- .header("User-Agent", "Man page crawler (info@manned.org; https://manned.org/)")
- .send()
- .map_err(|e| Error::new(ErrorKind::Other, format!("Reqwest: {}", e)))
- );
- if !res.status().is_success() {
+fn fetch(url: &str) -> Result<Box<dyn Read>> {
+ let res = ureq::get(url)
+ .set("User-Agent", "Man page crawler (info@manned.org; https://manned.org/)")
+ .call()
+ .map_err(|e| Error::new(ErrorKind::Other, format!("Ureq: {}", e)))?;
+ if res.status() != 200 {
return Err(Error::new(ErrorKind::Other, format!("HTTP: {}", res.status()) ));
}
- Ok(Box::new(res) as Box<Read>)
+ Ok(Box::new(res.into_reader()) as Box<dyn Read>)
}
-fn file(path: &str) -> Result<Box<Read>> {
- Ok(Box::new(try!(File::open(path))) as Box<Read>)
+fn file(path: &str) -> Result<Box<dyn Read>> {
+ Ok(Box::new(File::open(path)?) as Box<dyn Read>)
}
@@ -65,28 +50,27 @@ pub fn clear_cache() -> Result<()> {
impl<'a> Path<'a> {
- pub fn open(&self) -> Result<Box<Read>> {
- if let Ok(url) = Url::parse(self.path) {
- if url.scheme() != "http" {
- return Err(Error::new(ErrorKind::Other, "Invalid scheme"));
- }
-
+ pub fn open(&self) -> Result<Box<dyn Read>> {
+ if self.path.starts_with("http://") || self.path.starts_with("https://") {
if self.cache {
- let cfn = cache_fn(&url);
+ let hash = digest::digest(&digest::SHA256, self.path.as_bytes())
+ .as_ref()[0..8].into_iter()
+ .fold(0u64, |a, &e| (a<<8) + e as u64);
+
+ let cfn = format!("{}/{:x}", CACHE_PATH, hash);
if let Ok(f) = file(&cfn) {
return Ok(f);
}
{
- let mut rd = try!(fetch(url.as_str()));
- let mut wr = try!(File::create(&cfn));
- try!(copy(&mut rd, &mut wr));
+ let mut rd = fetch(self.path)?;
+ let mut wr = File::create(&cfn)?;
+ copy(&mut rd, &mut wr)?;
}
file(&cfn)
} else {
- fetch(url.as_str())
+ fetch(self.path)
}
-
} else if self.canbelocal {
file(self.path)
diff --git a/indexer/src/pkg.rs b/indexer/src/pkg.rs
index 93b7c14..11aab66 100644
--- a/indexer/src/pkg.rs
+++ b/indexer/src/pkg.rs
@@ -3,10 +3,10 @@ use std::io::{Error,ErrorKind,Read};
use postgres;
use chrono::NaiveDateTime;
-use open;
-use archread;
-use man;
-use archive::{Format,Archive,ArchiveEntry};
+use crate::open;
+use crate::archread;
+use crate::man;
+use crate::archive::{Format,Archive,ArchiveEntry};
pub static mut DRY_RUN: bool = false;
@@ -48,23 +48,27 @@ pub struct PkgOpt<'a> {
}
-fn insert_pkg(tr: &postgres::transaction::Transaction, opt: &PkgOpt) -> Option<i32> {
+fn insert_pkg(tr: &mut postgres::Transaction, opt: &PkgOpt) -> Option<i32> {
let pkginfo = format!("sys {} / {} / {} - {} @ {:?} @ {}", opt.sys, opt.cat, opt.pkg, opt.ver, opt.date, opt.file.path);
- // The ON CONFLICT .. DO UPDATE is used instead of DO NOTHING because in that case the
- // RETURNING clause wouldn't give us a package id.
- let q = "INSERT INTO packages (system, category, name) VALUES($1, $2, $3)
- ON CONFLICT ON CONSTRAINT packages_system_name_category_key DO UPDATE SET name=$3 RETURNING id";
- let pkgid: i32 = match tr.query(q, &[&opt.sys, &opt.cat, &opt.pkg]) {
+ // Use a custom CTE-based insert-or-update. Using an INSERT with an ON CONFLICT clause would be
+ // easier, but has the downside of allocating a new package id even if one already exists.
+ // The separate UPDATE query makes sure to unflag the package as dead while not causing any
+ // database writes when the row's already fine.
+ let q = "WITH p(id) AS (SELECT id FROM packages WHERE system = $1 AND category = $2 AND name = $3),
+ u AS (UPDATE packages SET dead = FALSE FROM p WHERE packages.id = p.id AND dead),
+ i(id) AS (INSERT INTO packages (system, category, name) SELECT $1, $2, $3 WHERE NOT EXISTS(SELECT 1 FROM p) RETURNING id)
+ SELECT id FROM p UNION SELECT id FROM i";
+ let pkgid: i32 = match tr.query_one(q, &[&opt.sys, &opt.cat, &opt.pkg]) {
Err(e) => {
error!("Can't insert package in database: {}", e);
return None;
},
- Ok(r) => r.get(0).get(0),
+ Ok(r) => r.get(0),
};
let q = "SELECT id FROM package_versions WHERE package = $1 AND version = $2";
- let res = tr.query(q, &[&pkgid, &opt.ver]).unwrap();
+ let res = tr.query_opt(q, &[&pkgid, &opt.ver]).unwrap();
let verid : i32;
@@ -73,33 +77,41 @@ fn insert_pkg(tr: &postgres::transaction::Transaction, opt: &PkgOpt) -> Option<i
_ => "1980-01-01", // Placeholder
};
- if res.is_empty() {
+ if res.is_none() {
let q = "INSERT INTO package_versions (package, version, released, arch) VALUES($1, $2, $3::text::date, $4) RETURNING id";
- verid = tr.query(q, &[&pkgid, &opt.ver, &date, &opt.arch]).unwrap().get(0).get(0);
+ verid = tr.query_one(q, &[&pkgid, &opt.ver, &date, &opt.arch]).unwrap().get(0);
info!("New package pkgid {} verid {}, {}", pkgid, verid, pkginfo);
Some(verid)
} else if opt.force {
// XXX: Should we update released & arch here?
- verid = res.get(0).get(0);
+ verid = res?.get(0);
info!("Overwriting package pkgid {} verid {}, {}", pkgid, verid, pkginfo);
- tr.query("DELETE FROM man WHERE package = $1", &[&verid]).unwrap();
+ tr.query("DELETE FROM files WHERE pkgver = $1", &[&verid]).unwrap();
Some(verid)
} else {
- debug!("Package already in database, pkgid {} verid {}, {}", pkgid, res.get(0).get::<usize,i32>(0), pkginfo);
+ debug!("Package already in database, pkgid {} verid {}, {}", pkgid, res?.get::<usize,i32>(0), pkginfo);
None
}
}
-fn insert_man_row(tr: &postgres::GenericConnection, verid: i32, path: &str, enc: &str, hash: &[u8]) {
+fn insert_man_row<T: postgres::GenericClient>(tr: &mut T, verid: i32, path: &str, enc: &str, content: i32) {
let (name, sect, locale) = man::parse_path(path).unwrap();
- let locale = if locale == "" { None } else { Some(locale) };
- if let Err(e) = tr.execute(
- "INSERT INTO man (package, name, filename, locale, hash, section, encoding) VALUES ($1, $2, '/'||$3, $4, $5, $6, $7)",
- &[&verid, &name, &path, &locale, &hash, &sect, &enc]
- ) {
+ let q = "WITH ms(id) AS (SELECT id FROM mans WHERE name = $2 AND section = $3),
+ mi(id) AS (INSERT INTO mans (name, section) SELECT $2, $3 WHERE NOT EXISTS(SELECT 1 FROM ms) RETURNING id),
+ m(id) AS (SELECT id FROM ms UNION SELECT id FROM mi),
+ ls(id) AS (SELECT id FROM locales WHERE locale = $5),
+ li(id) AS (INSERT INTO locales (locale) SELECT $5 WHERE NOT EXISTS(SELECT 1 FROM ls) RETURNING id),
+ l(id) AS (SELECT id FROM ls UNION SELECT id FROM li),
+ es(id) AS (SELECT id FROM encodings WHERE encoding = $6),
+ ei(id) AS (INSERT INTO encodings (encoding) SELECT $6 WHERE NOT EXISTS(SELECT 1 FROM es) RETURNING id),
+ e(id) AS (SELECT id FROM es UNION SELECT id FROM ei),
+ c(shorthash) AS (SELECT hash_to_shorthash(hash) FROM contents WHERE id = $4)
+ INSERT INTO files (pkgver, man, content, shorthash, locale, encoding, filename)
+ SELECT $1, m.id, $4, c.shorthash, l.id, e.id, '/'||$7 FROM m, l, e, c";
+ if let Err(e) = tr.execute(q, &[&verid, &name, &sect, &content, &locale, &enc, &path]) {
// I think this can only happen if archread gives us the same file twice, which really
// shouldn't happen. But I'd rather continue with an error logged than panic.
error!("Can't insert verid {} fn {}: {}", verid, path, e);
@@ -107,7 +119,7 @@ fn insert_man_row(tr: &postgres::GenericConnection, verid: i32, path: &str, enc:
}
-fn insert_man(tr: &postgres::GenericConnection, verid: i32, paths: &[&str], ent: &mut Read) {
+fn insert_man<T: postgres::GenericClient>(tr: &mut T, verid: i32, paths: &[&str], ent: &mut dyn Read) {
let (dig, enc, mut cont) = match man::decode(paths, ent) {
Err(e) => { error!("Error decoding {}: {}", paths[0], e); return },
Ok(x) => x,
@@ -119,27 +131,30 @@ fn insert_man(tr: &postgres::GenericConnection, verid: i32, paths: &[&str], ent:
cont = cont.replace(0 as char, "");
}
- tr.execute(
- "INSERT INTO contents (hash, content) VALUES($1, $2) ON CONFLICT (hash) DO NOTHING",
- &[&dig.as_ref(), &cont]
- ).unwrap();
+ let q = "WITH s(id) AS (SELECT id FROM contents WHERE hash = $1),
+ i(id) AS (INSERT INTO contents (hash, content) SELECT $1, $2 WHERE NOT EXISTS(SELECT 1 FROM s) RETURNING id)
+ SELECT id FROM s UNION SELECT id FROM i";
+ let id: i32 = tr.query_one(q, &[&dig.as_ref(), &cont]).unwrap().get(0);
for path in paths {
- insert_man_row(tr, verid, path, enc, dig.as_ref());
+ insert_man_row(tr, verid, path, enc, id);
info!("Inserted man page: {} ({})", path, enc);
}
}
-fn insert_link(tr: &postgres::GenericConnection, verid: i32, src: &str, dest: &str) {
- let res = tr.query("SELECT hash, encoding FROM man WHERE package = $1 AND filename = '/'||$2", &[&verid, &dest]).unwrap();
- if res.is_empty() { /* Can happen if man::decode() failed previously. */
- error!("Link to unindexed man page: {} -> {}", src, dest);
- return;
- }
- let hash: Vec<u8> = res.get(0).get(0);
- let enc: String = res.get(0).get(1);
- insert_man_row(tr, verid, src, &enc, &hash);
+fn insert_link<T>(tr: &mut T, verid: i32, src: &str, dest: &str) where T: postgres::GenericClient {
+ let q = "SELECT f.content, e.encoding FROM files f JOIN encodings e ON e.id = f.encoding WHERE pkgver = $1 AND filename = '/'||$2";
+ let res = match tr.query_opt(q, &[&verid, &dest]).unwrap() {
+ None => { /* Can happen if man::decode() failed previously. */
+ error!("Link to unindexed man page: {} -> {}", src, dest);
+ return;
+ },
+ Some(x) => x
+ };
+ let content: i32 = res.get(0);
+ let enc: String = res.get(1);
+ insert_man_row(tr, verid, src, &enc, content);
info!("Inserted man link: {} -> {}", src, dest);
}
@@ -173,19 +188,20 @@ fn with_pkg<F,T>(opt: &mut PkgOpt, cb: F) -> std::io::Result<T>
}
-fn index_pkg(tr: &postgres::GenericConnection, mut opt: PkgOpt, verid: i32) -> std::io::Result<()> {
- let indexfunc = |paths: &[&str], ent: &mut ArchiveEntry| {
- insert_man(tr, verid, paths, ent);
- Ok(()) /* Don't propagate errors, continue handling other man pages */
- };
-
+fn index_pkg<T: postgres::GenericClient>(tr: &mut T, mut opt: PkgOpt, verid: i32) -> std::io::Result<()> {
let missed = with_pkg(&mut opt, |e, opt| {
- archread::FileList::read(e, man::ismanpath, |ent| opt.date.update(ent), &indexfunc)
+ archread::FileList::read(e, man::ismanpath, |ent| opt.date.update(ent), |paths, ent| {
+ insert_man(tr, verid, paths, ent);
+ Ok(())
+ })
})?.links(|src, dest| { insert_link(tr, verid, src, dest) });
if let Some(missed) = missed {
warn!("Some links were missed, reading package again");
- with_pkg(&mut opt, |e, _| { missed.read(e, indexfunc) })?
+ with_pkg(&mut opt, |e, _| { missed.read(e, |paths, ent| {
+ insert_man(tr, verid, paths, ent);
+ Ok(())
+ }) })?
}
match opt.date {
@@ -201,21 +217,20 @@ fn index_pkg(tr: &postgres::GenericConnection, mut opt: PkgOpt, verid: i32) -> s
}
-pub fn pkg(conn: &postgres::GenericConnection, opt: PkgOpt) {
- let tr = conn.transaction().unwrap();
- tr.set_rollback();
+pub fn pkg<T>(conn: &mut T, opt: PkgOpt) where T: postgres::GenericClient {
+ let mut tr = conn.transaction().unwrap();
- let verid = match insert_pkg(&tr, &opt) { Some(x) => x, None => return };
+ let verid = match insert_pkg(&mut tr, &opt) { Some(x) => x, None => return };
if unsafe { DRY_RUN } {
return;
}
- match index_pkg(&tr, opt, verid) {
- Err(e) => error!("Error reading package: {}", e),
- Ok(_) => tr.set_commit()
+ if let Err(e) = index_pkg(&mut tr, opt, verid) {
+ error!("Error reading package: {}", e);
+ return;
}
- if let Err(e) = tr.finish() {
+ if let Err(e) = tr.commit() {
error!("Error finishing transaction: {}", e);
}
}
diff --git a/indexer/src/sys_alpine.rs b/indexer/src/sys_alpine.rs
new file mode 100644
index 0000000..241ca3e
--- /dev/null
+++ b/indexer/src/sys_alpine.rs
@@ -0,0 +1,99 @@
+use std::str::FromStr;
+use std::io::{Read,BufRead,BufReader};
+use postgres;
+
+use crate::archive;
+use crate::open;
+use crate::pkg;
+
+// https://git.alpinelinux.org/apk-tools/tree/doc/apk-repositories.5.scd
+// https://git.alpinelinux.org/apk-tools/tree/src/package.c#n874 (apk_pkg_write_index_entry)
+
+pub fn read_index<T: postgres::GenericClient, R: Read>(pg: &mut T, sys: i32, mirror: &str, repo: &str, lst: R) {
+ let rd = BufReader::new(lst);
+
+ let mut name = None;
+ let mut version = None;
+ let mut builddate = None;
+ let mut arch = None;
+ let mut lineno: u32 = 0;
+
+ for line in rd.lines() {
+ lineno += 1;
+ let line = match line {
+ Err(e) => { error!("Can't read package index: {}", e); return },
+ Ok(x) => x,
+ };
+
+ if line.starts_with("P:") {
+ name = Some(line[2..].to_string());
+ } else if line.starts_with("V:") {
+ version = Some(line[2..].to_string());
+ } else if line.starts_with("t:") {
+ builddate = i64::from_str(&line[2..]).ok();
+ } else if line.starts_with("A:") {
+ arch = Some(line[2..].to_string());
+ }
+ if line != "" {
+ continue;
+ }
+
+ if name.is_none() || version.is_none() {
+ warn!("Package without name or version on line {}", lineno);
+ return;
+ }
+
+ let pname = name.as_ref().unwrap();
+ let pver = version.as_ref().unwrap();
+ if pname == "man-pages" || pname.ends_with("-doc") {
+ let p = format!("{}/{}/x86_64/{}-{}.apk", mirror, repo, pname, pver);
+ pkg::pkg(pg, pkg::PkgOpt{
+ force: false,
+ sys: sys,
+ cat: repo,
+ pkg: pname,
+ ver: pver,
+ date: builddate.map(pkg::Date::Found).unwrap_or(pkg::Date::Max),
+ arch: arch.as_deref(),
+ file: open::Path{
+ path: &p,
+ cache: false,
+ canbelocal: false,
+ },
+ });
+ }
+
+ name = None;
+ version = None;
+ builddate = None;
+ arch = None;
+ }
+}
+
+
+pub fn sync<T: postgres::GenericClient>(pg: &mut T, sys: i32, mirror: &str, repo: &str) {
+ info!("Reading packages from {} {}", mirror, repo);
+
+ let path = format!("{}/{}/x86_64/APKINDEX.tar.gz", mirror, repo);
+ let path = open::Path{ path: &path, cache: true, canbelocal: false };
+ let mut index = match path.open() {
+ Err(e) => { error!("Can't read package index: {}", e); return },
+ Ok(x) => x,
+ };
+
+ let ent = match archive::Archive::open_archive(&mut index) {
+ Err(e) => { error!("Can't read package index: {}", e); return },
+ Ok(x) => x,
+ };
+
+ let r = archive::walk(ent, |x| {
+ if x.path() == Some("APKINDEX") {
+ read_index(pg, sys, mirror, repo, x);
+ }
+ Ok(true)
+ });
+
+ if let Err(e) = r {
+ error!("Error reading package index: {}", e);
+ }
+}
diff --git a/indexer/src/sys_arch.rs b/indexer/src/sys_arch.rs
index ee17266..4c0ea41 100644
--- a/indexer/src/sys_arch.rs
+++ b/indexer/src/sys_arch.rs
@@ -1,13 +1,14 @@
use std::str::FromStr;
use std::io::{Read,BufRead,BufReader,Result};
+use std::collections::HashSet;
use regex::Regex;
use chrono::NaiveDateTime;
use postgres;
-use archive;
-use open;
-use man;
-use pkg;
+use crate::archive;
+use crate::open;
+use crate::man;
+use crate::pkg;
struct Meta {
@@ -22,8 +23,7 @@ struct Meta {
fn read_files<T: Read>(lst: T) -> Result<bool> {
let rd = BufReader::new(lst);
for line in rd.lines() {
- let line = try!(line);
- if man::ismanpath(&line) {
+ if man::ismanpath(&line?) {
return Ok(true);
}
}
@@ -33,7 +33,7 @@ fn read_files<T: Read>(lst: T) -> Result<bool> {
fn read_desc(rd: &mut archive::ArchiveEntry) -> Result<Option<Meta>> {
let mut data = String::new();
- try!(rd.take(64*1024).read_to_string(&mut data));
+ rd.take(64*1024).read_to_string(&mut data)?;
let path = rd.path().unwrap();
lazy_static! {
@@ -75,7 +75,7 @@ fn read_desc(rd: &mut archive::ArchiveEntry) -> Result<Option<Meta>> {
}
-pub fn sync(pg: &postgres::GenericConnection, sys: i32, mirror: &str, repo: &str) {
+pub fn sync<T: postgres::GenericClient>(pg: &mut T, sys: i32, mirror: &str, repo: &str) {
info!("Reading packages from {} {}", mirror, repo);
let path = format!("{}/{}/os/x86_64/{1:}.files.tar.gz", mirror, repo);
@@ -92,14 +92,15 @@ pub fn sync(pg: &postgres::GenericConnection, sys: i32, mirror: &str, repo: &str
let mut hasman = false;
let mut meta = None;
+ let mut allpkgs = HashSet::new();
let r = archive::walk(ent, |x| {
if x.filetype() == archive::FileType::Directory {
hasman = false;
meta = None;
} else if x.path().unwrap().ends_with("/files") {
- hasman = try!(read_files(x));
+ hasman = read_files(x)?;
} else if x.path().unwrap().ends_with("/desc") {
- meta = try!(read_desc(x));
+ meta = read_desc(x)?;
}
if hasman && meta.is_some() {
@@ -121,6 +122,7 @@ pub fn sync(pg: &postgres::GenericConnection, sys: i32, mirror: &str, repo: &str
canbelocal: false,
},
});
+ allpkgs.insert(m.name.into_boxed_str());
}
Ok(true)
@@ -129,4 +131,30 @@ pub fn sync(pg: &postgres::GenericConnection, sys: i32, mirror: &str, repo: &str
if let Err(e) = r {
error!("Error reading package index: {}", e);
}
+ mark_dead(pg, sys, repo, allpkgs);
+}
+
+fn mark_dead<T: postgres::GenericClient>(pg: &mut T, sys: i32, repo: &str, pkgs: HashSet<Box<str>>) {
+ let mut dead = Vec::new();
+ for row in pg.query("SELECT id, name FROM packages WHERE system = $1 AND category = $2 AND NOT dead", &[&sys,&repo]).unwrap() {
+ let id: i32 = row.get(0);
+ let name: &str = row.get(1);
+ if !pkgs.contains(name) {
+ info!("Package not available in database anymore, marking dead; sys {} / {} / pkg {} ({})", sys, repo, id, name);
+ dead.push(id);
+ }
+ }
+ if dead.is_empty() {
+ return;
+ }
+
+ let mut tr = pg.transaction().unwrap();
+ let q = tr.prepare("UPDATE packages SET dead = TRUE WHERE id = $1").unwrap();
+ for id in dead {
+ tr.execute(&q, &[&id]).unwrap();
+ }
+
+ if let Err(e) = tr.commit() {
+ error!("Error finishing transaction: {}", e);
+ }
}
diff --git a/indexer/src/sys_deb.rs b/indexer/src/sys_deb.rs
index 46291bc..e92a7b7 100644
--- a/indexer/src/sys_deb.rs
+++ b/indexer/src/sys_deb.rs
@@ -5,10 +5,10 @@ use postgres;
use regex;
use regex::bytes::Regex;
-use man;
-use pkg;
-use open;
-use archive;
+use crate::man;
+use crate::pkg;
+use crate::open;
+use crate::archive;
// Reference: https://wiki.debian.org/RepositoryFormat
@@ -56,7 +56,7 @@ struct Pkg {
}
-fn handlepkg(pg: &postgres::GenericConnection, sys: i32, mirror: &str, manpkgs: &HashSet<String>, pkg: &Pkg) {
+fn handlepkg<T: postgres::GenericClient>(pg: &mut T, sys: i32, mirror: &str, manpkgs: &HashSet<String>, pkg: &Pkg) {
let name = match pkg.name { Some(ref x) => x, None => return };
if manpkgs.len() > 0 && !manpkgs.contains(name) {
return
@@ -94,7 +94,7 @@ fn handlepkg(pg: &postgres::GenericConnection, sys: i32, mirror: &str, manpkgs:
}
-pub fn sync(pg: &postgres::GenericConnection, sys: i32, mirror: &str, contents: Option<open::Path>, packages: open::Path) {
+pub fn sync<T: postgres::GenericClient >(pg: &mut T, sys: i32, mirror: &str, contents: Option<open::Path>, packages: open::Path) {
let manpkgs = match get_contents(contents) {
Err(e) => { error!("Can't read {}: {}", contents.unwrap().path, e); return },
Ok(x) => x,
diff --git a/indexer/src/sys_freebsd1.rs b/indexer/src/sys_freebsd1.rs
index f2e9e29..66c30b1 100644
--- a/indexer/src/sys_freebsd1.rs
+++ b/indexer/src/sys_freebsd1.rs
@@ -3,8 +3,8 @@ use std::io::Result;
use regex::Regex;
use postgres;
-use open;
-use pkg;
+use crate::open;
+use crate::pkg;
// Sync a FreeBSD <= 9.2 package respository.
@@ -26,7 +26,7 @@ use pkg;
// 'pear-PHPUnit version 1.3.3', because there is a 'pear' package in 'Latest' but no
// 'pear-PHPUnit'. This is handled with a static list of package names to add to the 'pkgs' list,
// see EXTRA_PKGS below.
-pub fn sync(pg: &postgres::GenericConnection, sys: i32, arch: &str, mirror: &str) -> Result<()> {
+pub fn sync<T: postgres::GenericClient>(pg: &mut T, sys: i32, arch: &str, mirror: &str) -> Result<()> {
let path = format!("{}Latest/", mirror);
let mut pkgs : Vec<String> = open::Path{path: &path, cache: true, canbelocal: false}
.dirlist()?.into_iter()
diff --git a/indexer/src/sys_freebsd2.rs b/indexer/src/sys_freebsd2.rs
index 193d7b0..9b42c8c 100644
--- a/indexer/src/sys_freebsd2.rs
+++ b/indexer/src/sys_freebsd2.rs
@@ -3,9 +3,9 @@ use regex::bytes::Regex;
use std::str;
use postgres;
-use open;
-use pkg;
-use archive::{Archive,ArchiveEntry};
+use crate::open;
+use crate::pkg;
+use crate::archive::{Archive,ArchiveEntry};
fn getpkgsite(mut ent: Option<ArchiveEntry>) -> Result<ArchiveEntry> {
@@ -19,7 +19,7 @@ fn getpkgsite(mut ent: Option<ArchiveEntry>) -> Result<ArchiveEntry> {
}
-pub fn sync(pg: &postgres::GenericConnection, sys: i32, mirror: &str) -> Result<()> {
+pub fn sync<T: postgres::GenericClient>(pg: &mut T, sys: i32, mirror: &str) -> Result<()> {
let path = format!("{}packagesite.txz", mirror);
let mut rd = open::Path{path: &path, cache: true, canbelocal: false}.open()?;
diff --git a/indexer/src/sys_rpm.rs b/indexer/src/sys_rpm.rs
index 6e16916..bf5dca0 100644
--- a/indexer/src/sys_rpm.rs
+++ b/indexer/src/sys_rpm.rs
@@ -2,41 +2,25 @@ use std::collections::HashSet;
use std::io::BufReader;
use std::str::FromStr;
use std::error::Error;
-use std::fmt;
use chrono::NaiveDateTime;
use postgres;
use quick_xml as xml;
use quick_xml::events::Event;
-use archive;
-use open;
-use pkg;
-use man;
+use crate::archive;
+use crate::open;
+use crate::pkg;
+use crate::man;
-// Ugh, quick-xml's Error type does not implement Error.
-#[derive(Debug)]
-struct XmlError(String);
-impl fmt::Display for XmlError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) }
-}
-impl Error for XmlError {
- fn description(&self) -> &str { self.0.as_ref() }
-}
-fn to_err(e: xml::Error) -> XmlError {
- XmlError(format!("{}", e))
-}
-
-
-
-fn xml_getattr(e: &xml::events::BytesStart, attr: &str) -> Result<String,Box<Error>> {
+fn xml_getattr(e: &xml::events::BytesStart, attr: &str) -> Result<String,Box<dyn Error>> {
for kv in e.attributes().with_checks(false) {
- let kv = kv.map_err(to_err)?;
+ let kv = kv?;
if kv.key == attr.as_bytes() {
return Ok(String::from_utf8(kv.value.into_owned())?);
}
}
- Err(Box::new(XmlError(format!("Attribute '{}' not found", attr))))
+ Err(Box::new(xml::Error::UnexpectedToken(format!("Attribute '{}' not found", attr))))
}
@@ -53,7 +37,7 @@ struct PkgInfo {
// Shared function to read primary.xml.gz and filelists.xml.gz. Runs the callback for each package
// with the info that was found.
-fn readpkgs<F>(url: String, mut cb: F) -> Result<(),Box<Error>>
+fn readpkgs<F>(url: String, mut cb: F) -> Result<(),Box<dyn Error>>
where F: FnMut(PkgInfo)
{
debug!("Reading {}", url);
@@ -74,8 +58,7 @@ fn readpkgs<F>(url: String, mut cb: F) -> Result<(),Box<Error>>
loop {
buf.clear();
- let event = xml.read_event(&mut buf);
- let event = event.map_err(to_err)?;
+ let event = xml.read_event(&mut buf)?;
match event {
@@ -97,7 +80,7 @@ fn readpkgs<F>(url: String, mut cb: F) -> Result<(),Box<Error>>
Event::Text(e) =>
if savestr {
- saved = Some(e.unescape_and_decode(&xml).map_err(to_err)?);
+ saved = Some(e.unescape_and_decode(&xml)?);
savestr = false
},
@@ -126,7 +109,7 @@ fn readpkgs<F>(url: String, mut cb: F) -> Result<(),Box<Error>>
// Reads repomd.xml and returns the path to the primary.xml.gz and filelists.xml.gz
-fn repomd(url: String) -> Result<(String,String),Box<Error>> {
+fn repomd(url: String) -> Result<(String,String),Box<dyn Error>> {
debug!("Reading {}", url);
let mut fd = open::Path{path: &url, cache: true, canbelocal: false}.open()?;
let mut xml = xml::Reader::from_reader(
@@ -143,7 +126,7 @@ fn repomd(url: String) -> Result<(String,String),Box<Error>> {
loop {
buf.clear();
- let event = xml.read_event(&mut buf).map_err(to_err)?;
+ let event = xml.read_event(&mut buf)?;
match event {
Event::Start(ref e) |
Event::Empty(ref e) => {
@@ -173,7 +156,7 @@ fn repomd(url: String) -> Result<(String,String),Box<Error>> {
}
-pub fn sync(pg: &postgres::GenericConnection, sys: i32, cat: &str, mirror: &str) -> Result<(),Box<Error>> {
+pub fn sync<T: postgres::GenericClient>(pg: &mut T, sys: i32, cat: &str, mirror: &str) -> Result<(),Box<dyn Error>> {
let(primary, filelists) = repomd(format!("{}repodata/repomd.xml", mirror))?;
let mut pkgswithman = HashSet::new();
diff --git a/indexer/src/sys_rpmdir.rs b/indexer/src/sys_rpmdir.rs
index 730aea6..b922b43 100644
--- a/indexer/src/sys_rpmdir.rs
+++ b/indexer/src/sys_rpmdir.rs
@@ -2,10 +2,10 @@ use std::io::Result;
use regex::Regex;
use postgres;
-use open;
-use pkg;
+use crate::open;
+use crate::pkg;
-pub fn sync(pg: &postgres::GenericConnection, sys: i32, cat: &str, mirror: &str) -> Result<()> {
+pub fn sync<T: postgres::GenericClient>(pg: &mut T, sys: i32, cat: &str, mirror: &str) -> Result<()> {
let pkgs : Vec<String> = open::Path{path: mirror, cache: true, canbelocal: false}
.dirlist()?.into_iter()
.filter_map(|(n,d)| if d { None } else { Some(n) })
diff --git a/lib/ManUtils/ManUtils.pm b/lib/ManUtils/ManUtils.pm
index 8b157ca..251a20b 100644
--- a/lib/ManUtils/ManUtils.pm
+++ b/lib/ManUtils/ManUtils.pm
@@ -13,6 +13,33 @@ require XSLoader;
XSLoader::load('ManUtils', $VERSION);
+sub _groff {
+ my($input, $output, $errors, $cv, @cmd) = @_;
+
+ # $MANWIDTH works by using the following groff options: -rLL=100n -rLT=100n
+ splice @cmd, 1, 0, qw|-Tutf8 -DUTF-8 -P-c -rLL=80n -rLT=80n|;
+
+ $input =
+ # Disable hyphenation, since that screws up man page references. :-(
+ ".hy 0\n.de hy\n..\n"
+ # Emulate man-db's --nj option
+ .".na\n.de ad\n..\n"
+ .$input;
+
+ my $groff = run_cmd \@cmd,
+ '<' => \$input,
+ '>' => \my $fmt,
+ '2>' => sub { if($_[0]) { chomp(my $e = $_[0]); push @$errors, "groff: $e" } };
+
+ $groff->cb(sub {
+ $$output = $fmt ? decode_utf8($fmt) : '';
+ $$output =~ s/[\t\s\r\n]+$//;
+ $cv->send;
+ });
+ $cv
+}
+
+
# Usage: $cv = fmt($input, \$output, \@errors)
# $cv = AnyEvent condition variable, fired when done.
# $input = UTF-8 encoded manual page source
@@ -24,18 +51,13 @@ sub fmt {
$$output = '';
@$errors = ();
- $input =
- # Disable hyphenation, since that screws up man page references. :-(
- ".hy 0\n.de hy\n..\n"
- # Emulate man-db's --nj option
- .".na\n.de ad\n..\n"
- .$input;
-
$input = encode_utf8($input);
+ # grog has a tendency to recognize pod2man generated pages as -ms, let's just work around that by enforcing -man
+ #return _groff $input, $output, $errors, $cv, 'groff', '-man' if $input =~ /^.\\" Automatically generated by Pod::Man/;
+
# Call grog to figure out which preprocessors to use.
- # $MANWIDTH works by using the following groff options: -rLL=100n -rLT=100n
- my $grog = run_cmd [qw|grog -Tutf8 -P-c -DUTF-8 -rLL=80n -rLT=80n -|],
+ my $grog = run_cmd [qw|grog -Tutf8 -DUTF-8 -|],
'<' => \$input,
'>' => \my $cmd,
'2>' => sub { $_[0] && push @$errors, "grog: $_[0]" };
@@ -66,20 +88,9 @@ sub fmt {
@cmd = (@cmd[0..$#cmd-1], $macros, $cmd[$#cmd]);
push @$errors, "grog detected several macro packages: $double. Using $macros. (@cmd)";
}
+ @cmd = map $_ eq '-ms' ? '-man' : $_, @cmd; # -ms is almost(?) always wrong.
- # grog 1.22.3 somehow loses the -P-c argument, let's make sure it's in the list.
- splice @cmd, 1, 0, '-P-c';
-
- my $groff = run_cmd \@cmd,
- '<' => \$input,
- '>' => \my $fmt,
- '2>' => sub { if($_[0]) { chomp(my $e = $_[0]); push @$errors, "groff: $e" } };
-
- $groff->cb(sub {
- $$output = $fmt ? decode_utf8($fmt) : '';
- $$output =~ s/[\t\s\r\n]+$//;
- $cv->send;
- });
+ _groff $input, $output, $errors, $cv, @cmd;
});
$cv;
diff --git a/schema.sql b/schema.sql
new file mode 100644
index 0000000..e2c02c3
--- /dev/null
+++ b/schema.sql
@@ -0,0 +1,121 @@
+CREATE TABLE systems (
+ -- Manually assigned number. The id is also used for ordering different
+ -- releases of the same system, as identified by 'name'.
+ id integer PRIMARY KEY,
+ name varchar NOT NULL,
+ release varchar,
+ short varchar NOT NULL
+);
+
+
+CREATE TABLE contents (
+ id SERIAL PRIMARY KEY,
+ -- 'hash' is the SHA1 of the man page file after decompression but *before*
+ -- encoding conversion and removing 0-bytes. This means taking sha1(content)
+ -- may not necessary match the hash, and it's possible for the same content
+ -- to be in the database under multiple hashes (but I suspect that's rare).
+ hash bytea NOT NULL UNIQUE,
+ content text NOT NULL
+);
+
+
+-- Unique man page, as identified by name & section
+CREATE TABLE mans (
+ id SERIAL PRIMARY KEY,
+ name text NOT NULL,
+ section text NOT NULL,
+ UNIQUE(name, section)
+);
+CREATE INDEX mans_name ON mans USING btree(lower(name) text_pattern_ops);
+
+
+-- List of man page locales for efficient referencing. Some locales include
+-- the encoding in their name, which isn't really correct or even necessary
+-- since we convert everything to UTF-8 anyway, but w/e, Can fix later.
+CREATE TABLE locales (
+ id SMALLSERIAL PRIMARY KEY,
+ locale text NOT NULL UNIQUE
+);
+
+
+-- List of encodings for efficient referencing.
+CREATE TABLE encodings (
+ id SMALLSERIAL PRIMARY KEY,
+ encoding text NOT NULL UNIQUE
+);
+
+
+CREATE TABLE packages (
+ id SERIAL PRIMARY KEY,
+ system integer NOT NULL REFERENCES systems(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ category varchar NOT NULL,
+ name varchar NOT NULL,
+ -- Whether this package has been seen in the last repository update. This
+ -- field is only updated for a few systems that are likely to delete packages
+ -- over time; non-rolling-release distros tend to not delete packages after
+ -- all.
+ -- Packages where the latest version does not have any man pages may also be
+ -- marked as dead even if the package is still available in the repos.
+ dead boolean NOT NULL DEFAULT FALSE,
+ UNIQUE(system, name, category) -- Note the order, lookups on (system,name) are common
+);
+
+
+CREATE TABLE package_versions (
+ id SERIAL PRIMARY KEY,
+ package integer NOT NULL REFERENCES packages(id) ON DELETE CASCADE,
+ version varchar NOT NULL,
+ released date NOT NULL,
+ arch varchar,
+ UNIQUE(package, version)
+);
+
+
+CREATE TABLE files (
+ pkgver integer NOT NULL REFERENCES package_versions(id) ON DELETE CASCADE,
+ man integer NOT NULL REFERENCES mans(id),
+ content integer NOT NULL REFERENCES content(id),
+ shorthash integer NOT NULL, -- cache: hash_to_shorthash(content.hash)
+ locale smallint NOT NULL REFERENCES locales(id)
+ -- The original encoding the man page was found in. This column isn't really
+ -- used at the moment, but is potentially useful when investigating encoding
+ -- issues.
+ encoding smallint NOT NULL REFERENCES encodings(id),
+ filename text NOT NULL,
+ PRIMARY KEY(pkgver, filename)
+);
+CREATE INDEX ON files (man, shorthash);
+CREATE INDEX ON files (content);
+
+
+-- For stats_cache
+\i util/update_indices.sql
+
+
+
+-- Interpret first 4 bytes of hash as a signed 32-bit integer.
+CREATE OR REPLACE FUNCTION hash_to_shorthash(hash bytea) RETURNS integer AS $$
+ SELECT CASE WHEN get_byte(hash, 3) < 128
+ THEN (get_byte(hash, 3)::int<<24) + (get_byte(hash, 2)::int<<16) + (get_byte(hash, 1)::int<<8) + get_byte(hash, 0)
+ ELSE -2147483648 + ((get_byte(hash, 3)::int - 128)<<24) + (get_byte(hash, 2)::int<<16) + (get_byte(hash, 1)::int<<8) + get_byte(hash, 0)
+ END;
+$$ LANGUAGE SQL IMMUTABLE;
+
+
+CREATE OR REPLACE FUNCTION is_english_locale(locale text) RETURNS bool AS $$
+ SELECT locale IS NULL OR locale = '' OR locale LIKE 'en%';
+$$ IMMUTABLE LANGUAGE SQL;
+
+
+CREATE OR REPLACE FUNCTION is_standard_man_location(path text) RETURNS bool AS $$
+ SELECT path LIKE '/usr/share/man/man%' OR path LIKE '/usr/local/man/man%';
+$$ IMMUTABLE LANGUAGE sql;
+
+-- Convenient function to match the first character of a string. Second argument must be lowercase 'a'-'z' or '0'.
+-- Postgres can inline and partially evaluate this function into the query plan, so it's fairly efficient.
+CREATE OR REPLACE FUNCTION match_firstchar(str text, chr text) RETURNS boolean AS $$
+ SELECT CASE WHEN chr = '0'
+ THEN (ascii(str) < 97 OR ascii(str) > 122) AND (ascii(str) < 65 OR ascii(str) > 90)
+ ELSE ascii(str) IN(ascii(chr),ascii(upper(chr)))
+ END;
+$$ LANGUAGE SQL IMMUTABLE;
diff --git a/sql/schema.sql b/sql/schema.sql
deleted file mode 100644
index 23f7110..0000000
--- a/sql/schema.sql
+++ /dev/null
@@ -1,281 +0,0 @@
-CREATE TABLE systems (
- id integer PRIMARY KEY, -- hardcoded ID.
- name varchar NOT NULL,
- release varchar,
- relorder integer NOT NULL DEFAULT 0, -- simple way of ordering different releases for the same system
- short varchar NOT NULL
-);
-
-CREATE TABLE contents (
- hash bytea PRIMARY KEY,
- content varchar NOT NULL
-);
-
-CREATE TABLE packages (
- id SERIAL PRIMARY KEY,
- system integer NOT NULL REFERENCES systems(id) ON DELETE CASCADE,
- category varchar,
- name varchar NOT NULL,
- UNIQUE(system, name, category) -- Note the order, lookups on (system,name) are common
-);
-
-CREATE TABLE package_versions (
- id SERIAL PRIMARY KEY,
- package integer NOT NULL REFERENCES packages(id) ON DELETE CASCADE,
- version varchar NOT NULL,
- released date NOT NULL,
- arch varchar,
- UNIQUE(package, version)
-);
-
-CREATE TABLE man (
- package integer NOT NULL REFERENCES package_versions(id) ON DELETE CASCADE,
- name varchar NOT NULL,
- filename varchar NOT NULL,
- locale varchar,
- hash bytea NOT NULL REFERENCES contents(hash),
- section varchar NOT NULL,
- encoding varchar,
- UNIQUE(package, filename)
-);
-
-CREATE INDEX ON man (hash);
-CREATE INDEX ON man (name);
-
-
-
-CREATE TABLE man_index AS SELECT DISTINCT name, section FROM man;
-CREATE INDEX ON man_index USING btree(lower(name) text_pattern_ops);
-
-CREATE TABLE stats_cache AS SELECT count(distinct hash) AS hashes, count(distinct name) AS mans, count(*) AS files, count(distinct package) AS packages FROM man;
-
-
-
-INSERT INTO systems (id, name, release, short, relorder) VALUES
- (1, 'Arch Linux', NULL, 'arch', 0),
- (2, 'Ubuntu', '4.10', 'ubuntu-warty', 0),
- (3, 'Ubuntu', '5.04', 'ubuntu-hoary', 1),
- (4, 'Ubuntu', '5.10', 'ubuntu-breezy', 2),
- (5, 'Ubuntu', '6.06', 'ubuntu-dapper', 3),
- (6, 'Ubuntu', '6.10', 'ubuntu-edgy', 4),
- (7, 'Ubuntu', '7.04', 'ubuntu-feisty', 5),
- (8, 'Ubuntu', '7.10', 'ubuntu-gutsy', 6),
- (9, 'Ubuntu', '8.04', 'ubuntu-hardy', 7),
- (10, 'Ubuntu', '8.10', 'ubuntu-intrepid', 8),
- (11, 'Ubuntu', '9.04', 'ubuntu-jaunty', 9),
- (12, 'Ubuntu', '9.10', 'ubuntu-karmic', 10),
- (13, 'Ubuntu', '10.04', 'ubuntu-lucid', 11),
- (14, 'Ubuntu', '10.10', 'ubuntu-maverick', 12),
- (15, 'Ubuntu', '11.04', 'ubuntu-natty', 13),
- (16, 'Ubuntu', '11.10', 'ubuntu-oneiric', 14),
- (17, 'Ubuntu', '12.04', 'ubuntu-precise', 15),
- (18, 'Debian', '1.1', 'debian-buzz', 0),
- (19, 'Debian', '1.2', 'debian-rex', 1),
- (20, 'Debian', '1.3', 'debian-bo', 2),
- (21, 'Debian', '2.0', 'debian-hamm', 3),
- (22, 'Debian', '2.1', 'debian-slink', 4),
- (23, 'Debian', '2.2', 'debian-potato', 5),
- (24, 'Debian', '3.0', 'debian-woody', 6),
- (25, 'Debian', '3.1', 'debian-sarge', 7),
- (26, 'Debian', '4.0', 'debian-etch', 8),
- (27, 'Debian', '5.0', 'debian-lenny', 9),
- (28, 'Debian', '6.0', 'debian-squeeze', 10),
- (29, 'FreeBSD', '1.0', 'freebsd-1.0', 0),
- (30, 'FreeBSD', '2.0.5', 'freebsd-2.0.5', 1),
- (31, 'FreeBSD', '2.1.5', 'freebsd-2.1.5', 2),
- (32, 'FreeBSD', '2.1.7', 'freebsd-2.1.7', 3),
- (33, 'FreeBSD', '2.2.2', 'freebsd-2.2.2', 4),
- (34, 'FreeBSD', '2.2.5', 'freebsd-2.2.5', 5),
- (35, 'FreeBSD', '2.2.6', 'freebsd-2.2.6', 6),
- (36, 'FreeBSD', '2.2.7', 'freebsd-2.2.7', 7),
- (37, 'FreeBSD', '2.2.8', 'freebsd-2.2.8', 8),
- (38, 'FreeBSD', '3.0', 'freebsd-3.0', 9),
- (39, 'FreeBSD', '3.1', 'freebsd-3.1', 10),
- (40, 'FreeBSD', '3.2', 'freebsd-3.2', 11),
- (41, 'FreeBSD', '3.3', 'freebsd-3.3', 12),
- (42, 'FreeBSD', '3.4', 'freebsd-3.4', 13),
- (43, 'FreeBSD', '3.5', 'freebsd-3.5', 14),
- (44, 'FreeBSD', '3.5.1', 'freebsd-3.5.1', 15),
- (45, 'FreeBSD', '4.0', 'freebsd-4.0', 16),
- (46, 'FreeBSD', '4.1', 'freebsd-4.1', 17),
- (47, 'FreeBSD', '4.1.1', 'freebsd-4.1.1', 18),
- (48, 'FreeBSD', '4.2', 'freebsd-4.2', 19),
- (49, 'FreeBSD', '4.3', 'freebsd-4.3', 20),
- (50, 'FreeBSD', '4.4', 'freebsd-4.4', 21),
- (51, 'FreeBSD', '4.5', 'freebsd-4.5', 22),
- (52, 'FreeBSD', '4.6', 'freebsd-4.6', 23),
- (53, 'FreeBSD', '4.6.2', 'freebsd-4.6.2', 24),
- (54, 'FreeBSD', '4.7', 'freebsd-4.7', 25),
- (55, 'FreeBSD', '4.8', 'freebsd-4.8', 26),
- (56, 'FreeBSD', '4.9', 'freebsd-4.9', 27),
- (57, 'FreeBSD', '4.10', 'freebsd-4.10', 28),
- (58, 'FreeBSD', '4.11', 'freebsd-4.11', 29),
- (59, 'FreeBSD', '5.0', 'freebsd-5.0', 30),
- (60, 'FreeBSD', '5.1', 'freebsd-5.1', 31),
- (61, 'FreeBSD', '5.2', 'freebsd-5.2', 32),
- (62, 'FreeBSD', '5.2.1', 'freebsd-5.2.1', 33),
- (63, 'FreeBSD', '5.3', 'freebsd-5.3', 34),
- (64, 'FreeBSD', '5.4', 'freebsd-5.4', 35),
- (65, 'FreeBSD', '5.5', 'freebsd-5.5', 36),
- (66, 'FreeBSD', '6.0', 'freebsd-6.0', 37),
- (67, 'FreeBSD', '6.1', 'freebsd-6.1', 38),
- (68, 'FreeBSD', '6.2', 'freebsd-6.2', 39),
- (69, 'FreeBSD', '6.3', 'freebsd-6.3', 40),
- (70, 'FreeBSD', '6.4', 'freebsd-6.4', 41),
- (71, 'FreeBSD', '7.0', 'freebsd-7.0', 42),
- (72, 'FreeBSD', '7.1', 'freebsd-7.1', 43),
- (73, 'FreeBSD', '7.2', 'freebsd-7.2', 44),
- (74, 'FreeBSD', '7.3', 'freebsd-7.3', 45),
- (75, 'FreeBSD', '7.4', 'freebsd-7.4', 46),
- (76, 'FreeBSD', '8.0', 'freebsd-8.0', 47),
- (77, 'FreeBSD', '8.1', 'freebsd-8.1', 48),
- (78, 'FreeBSD', '8.2', 'freebsd-8.2', 49),
- (79, 'FreeBSD', '8.3', 'freebsd-8.3', 50),
- (80, 'FreeBSD', '9.0', 'freebsd-9.0', 52),
- (81, 'Ubuntu', '12.10', 'ubuntu-quantal', 16),
- (82, 'Ubuntu', '13.04', 'ubuntu-raring', 17),
- (83, 'Debian', '7.0', 'debian-wheezy', 11),
- (84, 'FreeBSD', '8.4', 'freebsd-8.4', 51),
- (85, 'FreeBSD', '9.1', 'freebsd-9.1', 53),
- (86, 'FreeBSD', '9.2', 'freebsd-9.2', 54),
- (87, 'Ubuntu', '13.10', 'ubuntu-saucy', 18),
- (88, 'Ubuntu', '14.04', 'ubuntu-trusty', 19),
- (89, 'Ubuntu', '14.10', 'ubuntu-utopic', 20),
- (90, 'Ubuntu', '15.04', 'ubuntu-vivid', 21),
- (91, 'Debian', '8.0', 'debian-jessie', 12),
- (92, 'Ubuntu', '15.10', 'ubuntu-wily', 22),
- (93, 'Ubuntu', '16.04', 'ubuntu-xenial', 23),
- (94, 'FreeBSD', '9.3', 'freebsd-9.3', 55),
- (95, 'FreeBSD', '10.0', 'freebsd-10.0', 56),
- (96, 'FreeBSD', '10.1', 'freebsd-10.1', 57),
- (97, 'FreeBSD', '10.2', 'freebsd-10.2', 58),
- (98, 'FreeBSD', '10.3', 'freebsd-10.3', 59),
- (99, 'FreeBSD', '11.0', 'freebsd-11.0', 61),
- (100,'Ubuntu', '16.10', 'ubuntu-yakkety', 24),
- (101,'Fedora', '1', 'fedora-1', 0),
- (102,'Fedora', '2', 'fedora-2', 1),
- (103,'Fedora', '3', 'fedora-3', 2),
- (104,'Fedora', '4', 'fedora-4', 3),
- (105,'Fedora', '5', 'fedora-5', 4),
- (106,'Fedora', '6', 'fedora-6', 5),
- (107,'Fedora', '7', 'fedora-7', 6),
- (108,'Fedora', '8', 'fedora-8', 7),
- (109,'Fedora', '9', 'fedora-9', 8),
- (110,'Fedora', '10', 'fedora-10', 9),
- (111,'Fedora', '11', 'fedora-11', 10),
- (112,'Fedora', '12', 'fedora-12', 11),
- (113,'Fedora', '13', 'fedora-13', 12),
- (114,'Fedora', '14', 'fedora-14', 13),
- (115,'Fedora', '15', 'fedora-15', 14),
- (116,'Fedora', '16', 'fedora-16', 15),
- (117,'Fedora', '17', 'fedora-17', 16),
- (118,'Fedora', '18', 'fedora-18', 17),
- (119,'Fedora', '19', 'fedora-19', 18),
- (120,'Fedora', '20', 'fedora-20', 19),
- (121,'Fedora', '21', 'fedora-21', 20),
- (122,'Fedora', '22', 'fedora-22', 21),
- (123,'Fedora', '23', 'fedora-23', 22),
- (124,'Fedora', '24', 'fedora-24', 23),
- (125,'Fedora', '25', 'fedora-25', 24),
- (126,'Ubuntu', '17.04', 'ubuntu-zesty', 25),
- (127,'Debian', '9.0', 'debian-stretch', 13),
- (128,'Fedora', '26', 'fedora-26', 25),
- (129,'FreeBSD', '11.1', 'freebsd-11.1', 62),
- (130,'Ubuntu', '17.10', 'ubuntu-artful', 26),
- (131,'Fedora', '27', 'fedora-27', 26),
- (132,'FreeBSD', '10.4', 'freebsd-10.4', 60),
- (133,'CentOS', '2.1', 'centos-2.1', 1),
- (134,'CentOS', '3.1', 'centos-3.1', 2),
- (136,'CentOS', '3.3', 'centos-3.3', 4),
- (137,'CentOS', '3.4', 'centos-3.4', 5),
- (138,'CentOS', '3.5', 'centos-3.5', 6),
- (139,'CentOS', '3.6', 'centos-3.6', 7),
- (140,'CentOS', '3.7', 'centos-3.7', 8),
- (141,'CentOS', '3.8', 'centos-3.8', 9),
- (142,'CentOS', '3.9', 'centos-3.9', 10),
- (143,'CentOS', '4.0', 'centos-4.0', 11),
- (144,'CentOS', '4.1', 'centos-4.1', 12),
- (145,'CentOS', '4.2', 'centos-4.2', 13),
- (146,'CentOS', '4.3', 'centos-4.3', 14),
- (147,'CentOS', '4.4', 'centos-4.4', 15),
- (148,'CentOS', '4.5', 'centos-4.5', 16),
- (149,'CentOS', '4.6', 'centos-4.6', 17),
- (150,'CentOS', '4.7', 'centos-4.7', 18),
- (151,'CentOS', '4.8', 'centos-4.8', 19),
- (152,'CentOS', '4.9', 'centos-4.9', 20),
- (153,'CentOS', '5.0', 'centos-5.0', 21),
- (154,'CentOS', '5.1', 'centos-5.1', 22),
- (155,'CentOS', '5.2', 'centos-5.2', 23),
- (156,'CentOS', '5.3', 'centos-5.3', 24),
- (157,'CentOS', '5.4', 'centos-5.4', 25),
- (158,'CentOS', '5.5', 'centos-5.5', 26),
- (159,'CentOS', '5.6', 'centos-5.6', 27),
- (160,'CentOS', '5.7', 'centos-5.7', 28),
- (161,'CentOS', '5.8', 'centos-5.8', 29),
- (162,'CentOS', '5.9', 'centos-5.9', 30),
- (163,'CentOS', '5.10', 'centos-5.10', 31),
- (164,'CentOS', '5.11', 'centos-5.11', 32),
- (165,'CentOS', '6.0', 'centos-6.0', 33),
- (166,'CentOS', '6.1', 'centos-6.1', 34),
- (167,'CentOS', '6.2', 'centos-6.2', 35),
- (168,'CentOS', '6.3', 'centos-6.3', 36),
- (169,'CentOS', '6.4', 'centos-6.4', 37),
- (170,'CentOS', '6.5', 'centos-6.5', 38),
- (171,'CentOS', '6.6', 'centos-6.6', 39),
- (172,'CentOS', '6.7', 'centos-6.7', 40),
- (173,'CentOS', '6.8', 'centos-6.8', 41),
- (174,'CentOS', '6.9', 'centos-6.9', 42),
- (175,'CentOS', '7.0', 'centos-7.0', 44),
- (176,'CentOS', '7.1', 'centos-7.1', 45),
- (177,'CentOS', '7.2', 'centos-7.2', 46),
- (178,'CentOS', '7.3', 'centos-7.3', 47),
- (179,'CentOS', '7.4', 'centos-7.4', 48),
- (180,'Ubuntu', '18.04', 'ubuntu-bionic', 27),
- (181,'Fedora', '28', 'fedora-28', 27),
- (182,'CentOS', '7.5', 'centos-7.5', 49),
- (183,'CentOS', '6.10', 'centos-6.10', 43),
- (184,'FreeBSD', '11.2', 'freebsd-11.2', 63),
- (185,'Ubuntu', '18.10', 'ubuntu-cosmic', 28),
- (186,'Fedora', '29', 'fedora-29', 28),
- (187,'CentOS', '7.6', 'centos-7.6', 50),
- (188,'FreeBSD', '12.0', 'freebsd-12.0', 70),
- (189,'Ubuntu', '19.04', 'ubuntu-disco', 29),
- (190,'Debian', '10.0', 'debian-buster', 14),
- (191,'Fedora', '30', 'fedora-30', 29);
-
-
--- Removes any path components and compression extensions from the filename.
-CREATE OR REPLACE FUNCTION basename_from_filename(fn text) RETURNS text AS $$
-DECLARE
- ret text;
- tmp text;
-BEGIN
- ret := regexp_replace(fn, '^.+/([^/]+)', E'\\1');
- LOOP
- tmp := regexp_replace(regexp_replace(regexp_replace(ret, E'\\.gz$', ''), E'\\.lzma$', ''), E'\\.bz2$', '');
- EXIT WHEN tmp = ret;
- ret := tmp;
- END LOOP;
- RETURN ret;
-END;
-$$ LANGUAGE plpgsql;
-
-
-CREATE OR REPLACE FUNCTION section_from_filename(text) RETURNS text AS $$
- SELECT regexp_replace(basename_from_filename($1), E'^.+\\.([^.]+)$', E'\\1');
-$$ LANGUAGE SQL;
-
-
-CREATE OR REPLACE FUNCTION name_from_filename(text) RETURNS text AS $$
- SELECT regexp_replace(basename_from_filename($1), E'^(.+)\\.[^.]+$', E'\\1');
-$$ LANGUAGE SQL;
-
-
-CREATE OR REPLACE FUNCTION is_english_locale(locale text) RETURNS bool AS $$
- SELECT locale IS NULL OR locale LIKE 'en%';
-$$ IMMUTABLE LANGUAGE SQL;
-
-
-CREATE OR REPLACE FUNCTION is_standard_man_location(path text) RETURNS bool AS $$
- SELECT path LIKE '/usr/share/man/man%' OR path LIKE '/usr/local/man/man%';
-$$ IMMUTABLE LANGUAGE sql;
diff --git a/sql/update-2016-10-02.sql b/sql/update-2016-10-02.sql
deleted file mode 100644
index a669314..0000000
--- a/sql/update-2016-10-02.sql
+++ /dev/null
@@ -1,30 +0,0 @@
-CREATE TABLE packages (
- id SERIAL PRIMARY KEY,
- system integer NOT NULL REFERENCES systems(id),
- category varchar,
- name varchar NOT NULL,
- UNIQUE(system, name, category) -- Note the order, lookups on (system,name) are common
-);
-
-CREATE TABLE package_versions (
- id SERIAL PRIMARY KEY,
- package integer NOT NULL REFERENCES packages(id),
- version varchar NOT NULL,
- released date NOT NULL,
- UNIQUE(package, version)
-);
-
-INSERT INTO packages (system, category, name) SELECT system, category, name FROM package GROUP BY system, category, name;
-INSERT INTO package_versions (id, package, version, released)
- SELECT p.id, pn.id, p.version, p.released FROM package p JOIN packages pn ON pn.system = p.system AND pn.category = p.category AND pn.name = p.name;
-
-SELECT setval('package_versions_id_seq', nextval('package_id_seq'));
-
-ALTER TABLE man DROP CONSTRAINT man_package_fkey;
-ALTER TABLE man ADD FOREIGN KEY (package) REFERENCES package_versions(id);
-
--- Use a proper b-tree index
-DROP INDEX man_hash_idx;
-CREATE INDEX ON man (hash);
-
--- DROP TABLE package;
diff --git a/sql/update-2016-10-03.sql b/sql/update-2016-10-03.sql
deleted file mode 100644
index 68605d2..0000000
--- a/sql/update-2016-10-03.sql
+++ /dev/null
@@ -1,4 +0,0 @@
--- This check is not consistent with the HTML-check in util/add_dir.pl, but it
--- happens to match exactly the same man pages currently.
-DELETE FROM man WHERE section = 'html';
-DELETE FROM contents c WHERE NOT EXISTS(SELECT 1 FROM man m WHERE m.hash = c.hash);
diff --git a/sql/update-2016-10-06.sql b/sql/update-2016-10-06.sql
deleted file mode 100644
index ff4b394..0000000
--- a/sql/update-2016-10-06.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-ALTER TABLE packages DROP CONSTRAINT packages_system_fkey, ADD CONSTRAINT packages_system_fkey FOREIGN KEY(system) REFERENCES systems(id) ON DELETE CASCADE;
-ALTER TABLE package_versions DROP CONSTRAINT package_versions_package_fkey, ADD CONSTRAINT package_versions_package_fkey FOREIGN KEY(package) REFERENCES packages(id) ON DELETE CASCADE;
-ALTER TABLE man DROP CONSTRAINT man_package_fkey, ADD CONSTRAINT man_package_fkey FOREIGN KEY(package) REFERENCES package_versions(id) ON DELETE CASCADE;
diff --git a/sql/update-2016-10-09.sql b/sql/update-2016-10-09.sql
deleted file mode 100644
index 3c3ed7c..0000000
--- a/sql/update-2016-10-09.sql
+++ /dev/null
@@ -1,7 +0,0 @@
-CREATE OR REPLACE FUNCTION is_english_locale(locale text) RETURNS bool AS $$
- SELECT locale IS NULL OR locale LIKE 'en%';
-$$ IMMUTABLE LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION is_standard_man_location(path text) RETURNS bool AS $$
- SELECT path LIKE '/usr/share/man/man%' OR path LIKE '/usr/local/man/man%';
-$$ IMMUTABLE LANGUAGE sql;
diff --git a/sql/update-2016-10-16.sql b/sql/update-2016-10-16.sql
deleted file mode 100644
index 2a630a6..0000000
--- a/sql/update-2016-10-16.sql
+++ /dev/null
@@ -1,19 +0,0 @@
--- Various non-manpages
-DELETE FROM man
- WHERE filename ~ '/Makefile\.(in|am)$'
- OR filename ~ '/\.cvsignore(\.gz)?$'
- OR filename !~ '/[^/]*\.[^/]*$'
- OR filename ~ '/man\.tmp$';
-
--- Wrong locales, found with:
--- SELECT DISTINCT Locale FROM man ORDER BY locale;
-UPDATE man SET locale = NULL
- WHERE locale = '5man'
- OR locale = 'c'
- OR locale ~ '^man.?$'
- OR locale ~ '^Man-Part[12]$';
-
--- Man page containing only a '$1'. Likely a build failure in earlier FreeBSD releases.
-DELETE FROM man WHERE hash = '\x5ea7b8101325c704551852f70b652e0a2b0d7c12';
-
-DELETE FROM contents c WHERE NOT EXISTS(SELECT 1 FROM man m WHERE m.hash = c.hash);
diff --git a/sql/update-2016-11-06.sql b/sql/update-2016-11-06.sql
deleted file mode 100644
index 7f4e820..0000000
--- a/sql/update-2016-11-06.sql
+++ /dev/null
@@ -1,2 +0,0 @@
-ALTER TABLE package_versions ADD COLUMN arch varchar;
-ALTER TABLE man ADD COLUMN encoding varchar;
diff --git a/sql/update-2016-12-18.sql b/sql/update-2016-12-18.sql
deleted file mode 100644
index 479e114..0000000
--- a/sql/update-2016-12-18.sql
+++ /dev/null
@@ -1,26 +0,0 @@
--- Delete some non-man-pages, these are already blacklisted in indexer/man.rs:validate().
--- Found with:
--- select hash from contents where content like e'\x7fELF%' or length(content) < 9 or content = e'timestamp\n' or content = e'.so man3/\n';
-DELETE FROM man WHERE hash IN(
- '\x0c8b9d6f753e8d8ec9276bfe98e993a133847642',
- '\x2c0f4624792234e2c289eec5b6bad1c699f84128',
- '\x2d8b07a585e3f072aaa2c2b0ebac91d9039ccd54',
- '\x4853d24dbb7d81e4782ef1bb1162c143f808dda1',
- '\x6dfe263ccab32880795dff4479d990ade1daa839',
- '\x72d08cf649f7a5cb0a9434d5b591878b2f7a0df9',
- '\x816aff0cb37d6c9ccbfa48fffec83e39b37193fa',
- '\x8af6f3e189ca29abb3a0ba51d7ef5e7e70451639',
- '\x8e5113f6f47ce34e0437c2105441dbb70f01491a',
- '\x92d754c27d4a6f851505be63aad6366857060f42',
- '\x9312a9f378cc7750c4f473e3fdbd1d9b4aaf1efa',
- '\x9f83db09859f909ce36b5aa97ec412c09ea27a76',
- '\xadc83b19e793491b1c6ea0fd8b46cd9f32e592fc',
- '\xb226262bf9f49e1098612ffdfc01680f7f305f70',
- '\xc1a1a4edf60cfd417d52fc7bf1698bf0b6c814e6',
- '\xda39a3ee5e6b4b0d3255bfef95601890afd80709',
- '\xe04aededffd5ff6a3bc1a5294796ce1efa4dc68d',
- '\xfe847f886e2d883a946282a552123dbba00f9596',
- '\xffecacd94bd2bc4488db35a6b761ed430a65ac8f'
-);
-
-DELETE FROM contents c WHERE NOT EXISTS(SELECT 1 FROM man m WHERE m.hash = c.hash);
diff --git a/util/alpine.sh b/util/alpine.sh
new file mode 100755
index 0000000..fa63e1f
--- /dev/null
+++ b/util/alpine.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+
+. ./common.sh
+
+MIRROR=http://dl-cdn.alpinelinux.org/alpine/
+
+alp() {
+ local VER=$1
+ local REPOS=$2
+
+ for REPO in $REPOS; do
+ index alpine --sys alpine-$VER --mirror ${MIRROR}v$VER --repo $REPO
+ done
+}
+
+case "$1" in
+ 3.0)
+ alp 3.0 main
+ ;;
+ 3.1)
+ alp 3.1 main
+ ;;
+ 3.2)
+ alp 3.2 main
+ ;;
+ 3.3)
+ alp 3.3 "main community"
+ ;;
+ 3.4)
+ alp 3.4 "main community"
+ ;;
+ 3.5)
+ alp 3.5 "main community"
+ ;;
+ 3.6)
+ alp 3.6 "main community"
+ ;;
+ 3.7)
+ alp 3.7 "main community"
+ ;;
+ 3.8)
+ alp 3.8 "main community"
+ ;;
+ 3.9)
+ alp 3.9 "main community"
+ ;;
+ 3.10)
+ alp 3.10 "main community"
+ ;;
+ 3.11)
+ alp 3.11 "main community"
+ ;;
+ 3.12)
+ alp 3.12 "main community"
+ ;;
+ 3.13)
+ alp 3.13 "main community"
+ ;;
+ 3.14)
+ alp 3.14 "main community"
+ ;;
+ 3.15)
+ alp 3.15 "main community"
+ ;;
+ 3.16)
+ alp 3.16 "main community"
+ ;;
+ 3.17)
+ alp 3.17 "main community"
+ ;;
+ 3.18)
+ alp 3.18 "main community"
+ ;;
+ 3.19)
+ alp 3.19 "main community"
+ ;;
+ old)
+ $0 3.0
+ $0 3.1
+ $0 3.2
+ $0 3.3
+ $0 3.4
+ $0 3.5
+ $0 3.6
+ $0 3.7
+ $0 3.8
+ $0 3.9
+ $0 3.10
+ $0 3.11
+ $0 3.12
+ $0 3.13
+ $0 3.14
+ $0 3.15
+ ;;
+ current)
+ $0 3.16 # till 2024-05-23
+ $0 3.17 # till 2024-11-22
+ $0 3.18 # till 2025-05-09
+ $0 3.19 # till 2025-11-01
+ ;;
+ all)
+ $0 old
+ $0 current
+ ;;
+esac
diff --git a/util/arch.sh b/util/arch.sh
index 36e1b95..894bd91 100755
--- a/util/arch.sh
+++ b/util/arch.sh
@@ -2,7 +2,7 @@
. ./common.sh
-MIRROR=http://mirror.i3d.net/pub/archlinux/
+MIRROR=http://mirror.ams1.nl.leaseweb.net/archlinux/
case "$1" in
current)
diff --git a/util/centos.sh b/util/centos.sh
index ee879d2..5ad0541 100755
--- a/util/centos.sh
+++ b/util/centos.sh
@@ -4,6 +4,7 @@
VMIRROR=http://vault.centos.org/
CMIRROR=http://centos.mirrors.ovh.net/ftp.centos.org/
+SMIRROR=http://mirror.transip.net/centos-stream/
# Centos 3.1 - 3.6 (doesn't have useful repo metadata)
centa() {
@@ -38,6 +39,30 @@ centc() {
index rpm --sys centos-$VER --cat centosplus --mirror "$MIR$DIR/centosplus/x86_64/"
}
+# CentOS 8.0+
+centd() {
+ local VER=$1
+ local DIR=$2
+ local MIR=${3:-$VMIRROR}
+ index rpm --sys centos-$VER --cat BaseOS --mirror "$MIR$DIR/BaseOS/x86_64/os/"
+ index rpm --sys centos-$VER --cat AppStream --mirror "$MIR$DIR/AppStream/x86_64/os/"
+ index rpm --sys centos-$VER --cat PowerTools --mirror "$MIR$DIR/PowerTools/x86_64/os/"
+ index rpm --sys centos-$VER --cat extras --mirror "$MIR$DIR/extras/x86_64/os/"
+ index rpm --sys centos-$VER --cat centosplus --mirror "$MIR$DIR/centosplus/x86_64/os/"
+}
+
+# CentOS Stream 9+
+cente() {
+ local VER=$1
+ local DIR=$2
+ local MIR=${3:-$VMIRROR}
+ index rpm --sys centos-$VER --cat BaseOS --mirror "$MIR$DIR/BaseOS/x86_64/os/"
+ index rpm --sys centos-$VER --cat AppStream --mirror "$MIR$DIR/AppStream/x86_64/os/"
+ index rpm --sys centos-$VER --cat CRB --mirror "$MIR$DIR/CRB/x86_64/os/"
+ # There's also NFV and RT (with lots of overlap) and HighAvailability and ResilientStorage (with lots of overlap).
+ # Not sure which of those should be included.
+}
+
case "$1" in
2.1)
index rpmdir --sys centos-2.1 --cat core --mirror "${VMIRROR}2.1/final/i386/CentOS/RPMS/"
@@ -186,6 +211,39 @@ case "$1" in
7.6)
centc 7.6 7.6.1810 $CMIRROR
;;
+ 7.7)
+ centc 7.7 7.7.1908 $CMIRROR
+ ;;
+ 7.8)
+ centc 7.8 7.8.2003 $CMIRROR
+ ;;
+ 7.9)
+ centc 7.9 7.9.2009 $CMIRROR
+ ;;
+ 8.0)
+ centd 8.0 8.0.1905 $CMIRROR
+ ;;
+ 8.1)
+ centd 8.1 8.1.1911 $CMIRROR
+ ;;
+ 8.2)
+ centd 8.2 8.2.2004 $CMIRROR
+ ;;
+ 8.3)
+ centd 8.3 8.3.2011 $CMIRROR
+ ;;
+ 8.4)
+ centd 8.4 8.4.2105 $CMIRROR
+ ;;
+ 8.5)
+ centd 8.5 8.5.2111 $CMIRROR
+ ;;
+ 8-stream)
+ centd 8-stream 8-stream $CMIRROR
+ ;;
+ 9-stream)
+ cente 9-stream 9-stream $SMIRROR
+ ;;
old)
$0 2.1
$0 3.1
@@ -235,10 +293,20 @@ case "$1" in
$0 7.3
$0 7.4
$0 7.5
+ $0 7.6
+ $0 7.7
+ $0 7.8
+ $0 8.0
+ $0 8.1
+ $0 8.2
+ $0 8.3
+ $0 8.4
+ $0 8.5
;;
current)
- $0 6.10 # till 2020-11-30
- $0 7.6 # till 2024-06-30
+ $0 7.9 # till 2024-06-30
+ $0 8-stream
+ $0 9-stream
;;
all)
$0 old
diff --git a/util/cron.sh b/util/cron.sh
index 237f7d3..1da2321 100755
--- a/util/cron.sh
+++ b/util/cron.sh
@@ -3,15 +3,12 @@
PSQL="psql -U manned -Awtq"
+./alpine.sh current
./arch.sh current
./debian.sh current
./centos.sh current
./fedora.sh current
./ubuntu.sh current
-# Only update indices once a week (on mondays). This process is slow and the data doesn't often change anyway.
-if [ `date +%u` == 1 ]
-then
- echo "============ Updating SQL indices"
- $PSQL -f update_indices.sql
-fi
+echo "============ Updating SQL indices"
+$PSQL -f update_indices.sql
diff --git a/util/debian.sh b/util/debian.sh
index 52c9dd5..c91772c 100755
--- a/util/debian.sh
+++ b/util/debian.sh
@@ -63,6 +63,18 @@ case "$1" in
index_deb debian-buster $CMIRROR buster "main contrib non-free" cmp amd64
index_deb debian-buster $CMIRROR buster-updates "main contrib non-free" cmp amd64
;;
+ bullseye)
+ index_deb debian-bullseye $CMIRROR bullseye "main contrib non-free" cmp amd64
+ index_deb debian-bullseye $CMIRROR bullseye "main contrib non-free" cmp all
+ ;;
+ bookworm)
+ index_deb debian-bookworm $CMIRROR bookworm "main contrib non-free" cmp amd64
+ index_deb debian-bookworm $CMIRROR bookworm "main contrib non-free" cmp all
+ ;;
+ trixie)
+ index_deb debian-trixie $CMIRROR trixie "main contrib non-free" cmp amd64
+ index_deb debian-trixie $CMIRROR trixie "main contrib non-free" cmp all
+ ;;
old)
$0 buzz
$0 rex
@@ -77,10 +89,13 @@ case "$1" in
$0 squeeze
$0 wheezy
$0 jessie
+ $0 stretch
;;
current)
- $0 stretch
$0 buster
+ $0 bullseye
+ $0 bookworm
+ $0 trixie
;;
all)
$0 old
diff --git a/util/fedora.sh b/util/fedora.sh
index 8670f05..1d7df15 100755
--- a/util/fedora.sh
+++ b/util/fedora.sh
@@ -113,6 +113,42 @@ case "$1" in
index rpm --sys fedora-30 --cat everything --mirror "${CMIRROR}releases/30/Everything/x86_64/os/"
index rpm --sys fedora-30 --cat everything --mirror "${CMIRROR}updates/30/Everything/x86_64/"
;;
+ 31)
+ index rpm --sys fedora-31 --cat everything --mirror "${CMIRROR}releases/31/Everything/x86_64/os/"
+ index rpm --sys fedora-31 --cat everything --mirror "${CMIRROR}updates/31/Everything/x86_64/"
+ ;;
+ 32)
+ index rpm --sys fedora-32 --cat everything --mirror "${CMIRROR}releases/32/Everything/x86_64/os/"
+ index rpm --sys fedora-32 --cat everything --mirror "${CMIRROR}updates/32/Everything/x86_64/"
+ ;;
+ 33)
+ index rpm --sys fedora-33 --cat everything --mirror "${CMIRROR}releases/33/Everything/x86_64/os/"
+ index rpm --sys fedora-33 --cat everything --mirror "${CMIRROR}updates/33/Everything/x86_64/"
+ ;;
+ 34)
+ index rpm --sys fedora-34 --cat everything --mirror "${CMIRROR}releases/34/Everything/x86_64/os/"
+ index rpm --sys fedora-34 --cat everything --mirror "${CMIRROR}updates/34/Everything/x86_64/"
+ ;;
+ 35)
+ index rpm --sys fedora-35 --cat everything --mirror "${CMIRROR}releases/35/Everything/x86_64/os/"
+ index rpm --sys fedora-35 --cat everything --mirror "${CMIRROR}updates/35/Everything/x86_64/"
+ ;;
+ 36)
+ index rpm --sys fedora-36 --cat everything --mirror "${CMIRROR}releases/36/Everything/x86_64/os/"
+ index rpm --sys fedora-36 --cat everything --mirror "${CMIRROR}updates/36/Everything/x86_64/"
+ ;;
+ 37)
+ index rpm --sys fedora-37 --cat everything --mirror "${CMIRROR}releases/37/Everything/x86_64/os/"
+ index rpm --sys fedora-37 --cat everything --mirror "${CMIRROR}updates/37/Everything/x86_64/"
+ ;;
+ 38)
+ index rpm --sys fedora-38 --cat everything --mirror "${CMIRROR}releases/38/Everything/x86_64/os/"
+ index rpm --sys fedora-38 --cat everything --mirror "${CMIRROR}updates/38/Everything/x86_64/"
+ ;;
+ 39)
+ index rpm --sys fedora-39 --cat everything --mirror "${CMIRROR}releases/39/Everything/x86_64/os/"
+ index rpm --sys fedora-39 --cat everything --mirror "${CMIRROR}updates/39/Everything/x86_64/"
+ ;;
old)
$0 1
$0 2
@@ -142,10 +178,19 @@ case "$1" in
$0 26
$0 27
$0 28
- ;;
- current)
$0 29
$0 30
+ $0 31
+ $0 32
+ $0 33
+ $0 34
+ $0 35
+ $0 36
+ ;;
+ current)
+ $0 37
+ $0 38
+ $0 39
;;
all)
$0 old
diff --git a/util/freebsd.sh b/util/freebsd.sh
index 8eb56aa..285c9a3 100755
--- a/util/freebsd.sh
+++ b/util/freebsd.sh
@@ -583,12 +583,78 @@ case $1 in
index_core freebsd-11.2 "${MIR}base.txz" core-base 2018-06-27
index freebsd2 --sys freebsd-11.2 --mirror "$PKG"
;;
+ 11.3)
+ MIR="${CMIRROR}amd64/11.3-RELEASE/"
+ PKG="${PMIRROR}FreeBSD:11:amd64/release_3/"
+ index_core freebsd-11.3 "${MIR}base.txz" core-base 2019-07-09
+ index freebsd2 --sys freebsd-11.3 --mirror "$PKG"
+ ;;
+ 11.4)
+ MIR="${CMIRROR}amd64/11.4-RELEASE/"
+ PKG="${PMIRROR}FreeBSD:11:amd64/release_4/"
+ index_core freebsd-11.4 "${MIR}base.txz" core-base 2020-06-23
+ index freebsd2 --sys freebsd-11.4 --mirror "$PKG"
+ ;;
12.0)
MIR="${CMIRROR}amd64/12.0-RELEASE/"
PKG="${PMIRROR}FreeBSD:11:amd64/release_0/"
index_core freebsd-12.0 "${MIR}base.txz" core-base 2018-12-11
index freebsd2 --sys freebsd-12.0 --mirror "$PKG"
;;
+ 12.1)
+ MIR="${CMIRROR}amd64/12.1-RELEASE/"
+ PKG="${PMIRROR}FreeBSD:12:amd64/release_1/"
+ index_core freebsd-12.1 "${MIR}base.txz" core-base 2019-11-04
+ index freebsd2 --sys freebsd-12.1 --mirror "$PKG"
+ ;;
+ 12.2)
+ MIR="${CMIRROR}amd64/12.2-RELEASE/"
+ PKG="${PMIRROR}FreeBSD:12:amd64/release_2/"
+ index_core freebsd-12.2 "${MIR}base.txz" core-base 2020-10-27
+ index freebsd2 --sys freebsd-12.2 --mirror "$PKG"
+ ;;
+ 12.3)
+ MIR="${CMIRROR}amd64/12.3-RELEASE/"
+ PKG="${PMIRROR}FreeBSD:12:amd64/release_3/"
+ index_core freebsd-12.3 "${MIR}base.txz" core-base 2021-12-07
+ index freebsd2 --sys freebsd-12.3 --mirror "$PKG"
+ ;;
+ 12.4)
+ MIR="${CMIRROR}amd64/12.4-RELEASE/"
+ PKG="${PMIRROR}FreeBSD:12:amd64/release_4/"
+ index_core freebsd-12.4 "${MIR}base.txz" core-base 2022-12-05
+ index freebsd2 --sys freebsd-12.4 --mirror "$PKG"
+ ;;
+ 13.0)
+ MIR="${CMIRROR}amd64/13.0-RELEASE/"
+ PKG="${PMIRROR}FreeBSD:13:amd64/release_0/"
+ index_core freebsd-13.0 "${MIR}base.txz" core-base 2021-04-13
+ index freebsd2 --sys freebsd-13.0 --mirror "$PKG"
+ ;;
+ 13.1)
+ MIR="${CMIRROR}amd64/13.1-RELEASE/"
+ PKG="${PMIRROR}FreeBSD:13:amd64/release_1/"
+ index_core freebsd-13.1 "${MIR}base.txz" core-base 2022-05-16
+ index freebsd2 --sys freebsd-13.1 --mirror "$PKG"
+ ;;
+ 13.2)
+ MIR="${CMIRROR}amd64/13.2-RELEASE/"
+ PKG="${PMIRROR}FreeBSD:13:amd64/release_2/"
+ index_core freebsd-13.2 "${MIR}base.txz" core-base 2023-04-11
+ index freebsd2 --sys freebsd-13.2 --mirror "$PKG"
+ ;;
+ 13.3)
+ MIR="${CMIRROR}amd64/13.3-RELEASE/"
+ PKG="${PMIRROR}FreeBSD:13:amd64/release_3/"
+ index_core freebsd-13.3 "${MIR}base.txz" core-base 2024-03-05
+ index freebsd2 --sys freebsd-13.3 --mirror "$PKG"
+ ;;
+ 14.0)
+ MIR="${CMIRROR}amd64/14.0-RELEASE/"
+ PKG="${PMIRROR}FreeBSD:14:amd64/release_0/"
+ index_core freebsd-14.0 "${MIR}base.txz" core-base 2023-11-20
+ index freebsd2 --sys freebsd-14.0 --mirror "$PKG"
+ ;;
old)
$0 1.0
$0 2.0.5
@@ -654,6 +720,17 @@ case $1 in
$0 11.0
$0 11.1
$0 11.2
+ $0 11.3
+ $0 11.4
$0 12.0
+ $0 12.1
+ $0 12.2
+ $0 12.3
+ $0 12.4
+ $0 13.0
+ $0 13.1
+ $0 13.2
+ $0 13.3
+ $0 14.0
;;
esac
diff --git a/util/netbsd.sh b/util/netbsd.sh
new file mode 100755
index 0000000..3153e58
--- /dev/null
+++ b/util/netbsd.sh
@@ -0,0 +1,346 @@
+#!/bin/sh
+
+. ./common.sh
+
+CMIRROR=http://cdn.netbsd.org/pub/NetBSD/
+AMIRROR=http://archive.netbsd.org/pub/NetBSD-archive/
+
+# NetBSD's distribution format has been delightfully stable across the years.
+# This directory structure and the exact list of sets has been pretty much the
+# same since 1.3.
+index_base() {
+ local ver=$1
+ local date=$2
+ local ext=${3:-tar.xz}
+ local mirror=${4:-$CMIRROR}
+ local arch=${5:-amd64}
+ for pkg in comp games man text xbase xcomp xserver; do
+ index pkg --sys netbsd-$ver --cat base --pkg $pkg --ver $ver --date $date "${mirror}NetBSD-$ver/$arch/binary/sets/$pkg.$ext"
+ done
+}
+
+case $1 in
+ 1.3)
+ index_base 1.3 1998-01-03 tgz $AMIRROR i386
+ ;;
+
+ 1.3.2)
+ index_base 1.3.2 1998-05-29 tgz $AMIRROR i386
+ ;;
+
+ 1.3.3)
+ index_base 1.3.3 1998-12-23 tgz $AMIRROR i386
+ ;;
+
+ 1.4)
+ index_base 1.4 1999-05-12 tgz $AMIRROR i386
+ ;;
+
+ 1.4.1)
+ index_base 1.4.1 1999-08-26 tgz $AMIRROR i386
+ ;;
+
+ 1.4.2)
+ index_base 1.4.2 2000-03-21 tgz $AMIRROR i386
+ ;;
+
+ 1.4.3)
+ index_base 1.4.3 2000-11-25 tgz $AMIRROR i386
+ ;;
+
+ 1.5)
+ index_base 1.5 2000-12-06 tgz $AMIRROR i386
+ ;;
+
+ 1.5.1)
+ index_base 1.5.1 2001-07-11 tgz $AMIRROR i386
+ ;;
+
+ 1.5.2)
+ index_base 1.5.2 2001-09-13 tgz $AMIRROR i386
+ ;;
+
+ 1.5.3)
+ index_base 1.5.3 2002-07-22 tgz $AMIRROR i386
+ ;;
+
+ 1.6)
+ index_base 1.6 2002-09-14 tgz $AMIRROR i386
+ ;;
+
+ 1.6.1)
+ index_base 1.6.1 2003-04-21 tgz $AMIRROR i386
+ ;;
+
+ 1.6.2)
+ index_base 1.6.2 2004-03-01 tgz $AMIRROR i386
+ ;;
+
+ 2.0)
+ index_base 2.0 2004-12-09 tgz $AMIRROR i386
+ ;;
+
+ 2.0.2)
+ index_base 2.0.2 2005-04-14 tgz $AMIRROR i386
+ ;;
+
+ # Archive has no binary files for this release :(
+ #2.0.3)
+ # index_base 2.0.3 2005-10-31 tgz $AMIRROR i386
+ # ;;
+
+ 2.1)
+ index_base 2.1 2005-11-02 tgz $AMIRROR i386
+ ;;
+
+ 3.0)
+ index_base 3.0 2005-12-23 tgz $AMIRROR i386
+ ;;
+
+ 3.0.1)
+ index_base 3.0.1 2006-07-24 tgz $AMIRROR i386
+ ;;
+
+ 3.0.2)
+ index_base 3.0.2 2006-11-04 tgz $AMIRROR i386
+ ;;
+
+ 3.1)
+ index_base 3.1 2006-11-04 tgz $AMIRROR i386
+ ;;
+
+ 4.0)
+ index_base 4.0 2007-12-19 tgz $AMIRROR i386
+ ;;
+
+ 4.0.1)
+ index_base 4.0.1 2008-10-14 tgz $AMIRROR i386
+ ;;
+
+ 5.0)
+ index_base 5.0 2009-04-29 tgz $AMIRROR i386
+ ;;
+
+ 5.0.1)
+ index_base 5.0.1 2009-08-02 tgz $AMIRROR i386
+ ;;
+
+ 5.0.2)
+ index_base 5.0.2 2010-02-12 tgz $AMIRROR i386
+ ;;
+
+ 5.1)
+ index_base 5.1 2010-11-19 tgz $AMIRROR i386
+ ;;
+
+ 5.1.2)
+ index_base 5.1.2 2012-02-02 tgz $AMIRROR i386
+ ;;
+
+ 5.1.3)
+ index_base 5.1.3 2012-09-28 tgz $AMIRROR i386
+ ;;
+
+ 5.1.4)
+ index_base 5.1.4 2014-01-27 tgz $AMIRROR i386
+ ;;
+
+ 5.1.5)
+ index_base 5.1.5 2014-11-15 tgz $AMIRROR i386
+ ;;
+
+ 5.2)
+ index_base 5.2 2012-12-03 tgz $AMIRROR i386
+ ;;
+
+ 5.2.1)
+ index_base 5.2.1 2012-09-28 tgz $AMIRROR i386
+ ;;
+
+ 5.2.2)
+ index_base 5.2.2 2014-01-27 tgz $AMIRROR i386
+ ;;
+
+ 5.2.3)
+ index_base 5.2.3 2014-11-15 tgz $AMIRROR i386
+ ;;
+
+ 6.0)
+ index_base 6.0 2012-10-17 tgz $AMIRROR
+ ;;
+
+ 6.0.1)
+ index_base 6.0.1 2012-12-26 tgz $AMIRROR
+ ;;
+
+ 6.0.2)
+ index_base 6.0.2 2013-05-18 tgz $AMIRROR
+ ;;
+
+ 6.0.3)
+ index_base 6.0.3 2013-09-30 tgz $AMIRROR
+ ;;
+
+ 6.0.4)
+ index_base 6.0.4 2014-01-27 tgz $AMIRROR
+ ;;
+
+ 6.0.5)
+ index_base 6.0.5 2014-04-12 tgz $AMIRROR
+ ;;
+
+ 6.0.6)
+ index_base 6.0.6 2014-09-22 tgz $AMIRROR
+ ;;
+
+ 6.1)
+ index_base 6.1 2013-05-18 tgz $AMIRROR
+ ;;
+
+ 6.1.1)
+ index_base 6.1.1 2013-08-15 tgz $AMIRROR
+ ;;
+
+ 6.1.2)
+ index_base 6.1.2 2013-09-26 tgz $AMIRROR
+ ;;
+
+ 6.1.3)
+ index_base 6.1.3 2014-01-18 tgz $AMIRROR
+ ;;
+
+ 6.1.4)
+ index_base 6.1.4 2014-04-12 tgz $AMIRROR
+ ;;
+
+ 6.1.5)
+ index_base 6.1.5 2014-09-22 tgz $AMIRROR
+ ;;
+
+ 7.0)
+ index_base 7.0 2015-09-25 tgz $AMIRROR
+ ;;
+
+ 7.0.1)
+ index_base 7.0.1 2016-05-22 tgz $AMIRROR
+ ;;
+
+ 7.0.2)
+ index_base 7.0.2 2016-10-21 tgz $AMIRROR
+ ;;
+
+ 7.1)
+ index_base 7.1 2017-03-11 tgz $AMIRROR
+ ;;
+
+ 7.1.1)
+ index_base 7.1.1 2017-12-22 tgz $AMIRROR
+ ;;
+
+ 7.1.2)
+ index_base 7.1.2 2018-03-15 tgz $AMIRROR
+ ;;
+
+ 7.2)
+ index_base 7.2 2018-08-29 tgz $AMIRROR
+ ;;
+
+ 8.0)
+ index_base 8.0 2018-07-17 tgz $AMIRROR
+ ;;
+
+ 8.1)
+ index_base 8.1 2019-05-31 tgz $AMIRROR
+ ;;
+
+ 8.2)
+ index_base 8.2 2020-03-31 tgz $AMIRROR
+ ;;
+
+ 9.0)
+ index_base 9.0 2020-02-14
+ ;;
+
+ 9.1)
+ index_base 9.1 2020-10-18
+ ;;
+
+ 9.2)
+ index_base 9.2 2021-05-12
+ ;;
+
+ 9.3)
+ index_base 9.3 2022-08-04
+ ;;
+
+ 10.0)
+ index_base 10.0 2024-03-28
+ ;;
+
+ old)
+ $0 1.3
+ $0 1.3.2
+ $0 1.3.3
+ $0 1.4
+ $0 1.4.1
+ $0 1.4.2
+ $0 1.4.3
+ $0 1.5
+ $0 1.5.1
+ $0 1.5.2
+ $0 1.5.3
+ $0 1.6
+ $0 1.6.1
+ $0 1.6.2
+ $0 2.0
+ $0 2.0.2
+ #$0 2.0.3
+ $0 2.1
+ $0 3.0
+ $0 3.0.1
+ $0 3.0.2
+ $0 3.1
+ $0 4.0
+ $0 4.0.1
+ $0 5.0
+ $0 5.0.1
+ $0 5.0.2
+ $0 5.1
+ $0 5.1.2
+ $0 5.1.3
+ $0 5.1.4
+ $0 5.1.5
+ $0 5.2
+ $0 5.2.1
+ $0 5.2.2
+ $0 5.2.3
+ $0 6.0
+ $0 6.0.1
+ $0 6.0.2
+ $0 6.0.3
+ $0 6.0.4
+ $0 6.0.5
+ $0 6.0.6
+ $0 6.1
+ $0 6.1.1
+ $0 6.1.2
+ $0 6.1.3
+ $0 6.1.4
+ $0 6.1.5
+ $0 7.0
+ $0 7.0.1
+ $0 7.0.2
+ $0 7.1
+ $0 7.1.1
+ $0 7.1.2
+ $0 7.2
+ $0 8.0
+ $0 8.1
+ $0 8.2
+ $0 9.0
+ $0 9.1
+ $0 9.2
+ $0 9.3
+ $0 10.0
+ ;;
+esac
diff --git a/util/ubuntu.sh b/util/ubuntu.sh
index bdd5e8f..0a7ba6f 100755
--- a/util/ubuntu.sh
+++ b/util/ubuntu.sh
@@ -3,7 +3,7 @@
. ./common.sh
AMIRROR=http://old-releases.ubuntu.com/ubuntu/
-CMIRROR=http://nl.archive.ubuntu.com/ubuntu/
+CMIRROR=http://ftp.nluug.nl/os/Linux/distr/ubuntu/
# Shortcut for a standard Ubuntu repo, usage:
@@ -116,6 +116,33 @@ case $1 in
disco)
stdrepo disco $CMIRROR amd64
;;
+ eoan)
+ stdrepo eoan $CMIRROR amd64
+ ;;
+ focal)
+ stdrepo focal $CMIRROR amd64
+ ;;
+ groovy)
+ stdrepo groovy $CMIRROR amd64
+ ;;
+ hirsute)
+ stdrepo hirsute $CMIRROR amd64
+ ;;
+ impish)
+ stdrepo impish $CMIRROR amd64
+ ;;
+ jammy)
+ stdrepo jammy $CMIRROR amd64
+ ;;
+ kinetic)
+ stdrepo kinetic $CMIRROR amd64
+ ;;
+ lunar)
+ stdrepo lunar $CMIRROR amd64
+ ;;
+ mantic)
+ stdrepo mantic $CMIRROR amd64
+ ;;
old)
$0 warty
$0 hoary
@@ -136,19 +163,28 @@ case $1 in
$0 raring
$0 quantal
$0 saucy
+ $0 trusty
$0 utopic
$0 vivid
$0 wily
+ $0 xenial
$0 yakkety
$0 zesty
$0 artful
+ $0 cosmic
+ $0 disco
+ $0 eoan
+ $0 groovy
+ $0 hirsute
+ $0 impish
+ $0 kinetic
;;
current)
- $0 trusty # until 2019-04
- $0 xenial # until 2021-04
- $0 bionic # until 2023-04
- $0 cosmic # until 2019-07
- $0 disco # until 2020-01
+ $0 bionic # until 2028-04
+ $0 focal # until 2030-04
+ $0 jammy # until 2032-04
+ $0 lunar # until 2024-01
+ $0 mantic # until 2024-07
;;
all)
$0 old
diff --git a/util/update_indices.sql b/util/update_indices.sql
index a785ab7..b977d8a 100644
--- a/util/update_indices.sql
+++ b/util/update_indices.sql
@@ -2,14 +2,10 @@
-- the table being replaced. The site should remain responsive while these
-- queries are run.
BEGIN;
-CREATE TABLE man_index_new AS SELECT DISTINCT name, section FROM man;
-CREATE INDEX ON man_index_new USING btree(lower(name) text_pattern_ops);
-DROP TABLE man_index;
-ALTER TABLE man_index_new RENAME TO man_index;
-COMMIT;
-
-BEGIN;
-CREATE TABLE stats_cache_new AS SELECT count(distinct hash) AS hashes, count(distinct name) AS mans, count(*) AS files, count(distinct package) AS packages FROM man;
+CREATE TABLE stats_cache_new AS
+ SELECT (SELECT count(*) FROM contents) AS hashes,
+ (SELECT count(distinct name) FROM mans) AS mans, *
+ FROM (SELECT count(*), count(distinct pkgver) FROM files) x(files, packages);
DROP TABLE stats_cache;
ALTER TABLE stats_cache_new RENAME TO stats_cache;
COMMIT;
diff --git a/web/Cargo.lock b/web/Cargo.lock
index 1727e7b..0871c27 100644
--- a/web/Cargo.lock
+++ b/web/Cargo.lock
@@ -2,74 +2,46 @@
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
-version = "0.7.3"
+version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
- "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr",
]
[[package]]
name = "lazy_static"
-version = "1.3.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "memchr"
-version = "2.2.0"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "regex"
-version = "1.1.6"
+version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
- "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
]
[[package]]
name = "regex-syntax"
-version = "0.6.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "thread_local"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "ucd-util"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "utf8-ranges"
-version = "1.0.2"
+version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "web"
version = "0.1.0"
dependencies = [
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static",
+ "regex",
]
-
-[metadata]
-"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c"
-"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
-"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
-"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58"
-"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
-"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
-"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
-"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
diff --git a/www/images/alpine.png b/www/images/alpine.png
new file mode 100644
index 0000000..ccc839b
--- /dev/null
+++ b/www/images/alpine.png
Binary files differ
diff --git a/www/images/gradients.png b/www/images/gradients.png
deleted file mode 100644
index c6cb96d..0000000
--- a/www/images/gradients.png
+++ /dev/null
Binary files differ
diff --git a/www/images/netbsd.png b/www/images/netbsd.png
new file mode 100644
index 0000000..c4a78d0
--- /dev/null
+++ b/www/images/netbsd.png
Binary files differ
diff --git a/www/images/search.png b/www/images/search.png
deleted file mode 100644
index c1bd5cf..0000000
--- a/www/images/search.png
+++ /dev/null
Binary files differ
diff --git a/www/index.pl b/www/index.pl
index 0df8980..fbec00f 100755
--- a/www/index.pl
+++ b/www/index.pl
@@ -1,1135 +1,1177 @@
#!/usr/bin/perl
-use strict;
+use v5.26;
use warnings;
-use TUWF ':html', 'html_escape', ':xml';
-use JSON::XS;
+use TUWF ':html5_', ':xml';
use POSIX 'ceil';
+use SQL::Interp 'sql', 'sql_interp';
+use Time::Local 'timegm';
use Cwd 'abs_path';
our $ROOT;
BEGIN { ($ROOT = abs_path $0) =~ s{/www/index\.pl$}{}; }
+# Force the pure-perl AnyEvent backend; More lightweight and we don't need the
+# performance of EV. Fixes an issue with subprocess spawning under TUWF's
+# built-in web server that I haven't been able to track down.
+BEGIN { $ENV{PERL_ANYEVENT_MODEL} = 'Perl'; }
use lib "$ROOT/lib/ManUtils/inst/lib/perl5";
use ManUtils;
TUWF::set(
- logfile => $ENV{TUWF_LOG},
- db_login => [undef, undef, undef],
- debug => 0,
- xml_pretty => 0,
- log_slow_pages => 500,
- # Cache the system information
- pre_request_handler => sub {
- my $self = shift;
- if(!$self->{systems}) {
- $self->{systems} = $self->dbSystemGet;
- $_->{full} = $_->{name}.($_->{release}?' '.$_->{release}:'') for(@{$self->{systems}});
- $self->{sysbyid} = { map +($_->{id}, $_), @{$self->{systems}} };
- $self->{sysbyshort} = { map +($_->{short}, $_), @{$self->{systems}} };
- }
- 1;
- },
- error_404_handler => sub {
- my $self = shift;
- $self->resStatus(404);
- my $title = 'No manual entry for '.$self->reqPath;
- $self->htmlHeader(title => $title);
- h1 $title;
- p 'That is, the page you were looking for doesn\'t exist.';
- $self->htmlFooter;
- },
+ logfile => $ENV{TUWF_LOG},
+ db_login => [undef, undef, undef],
+ debug => $ENV{TUWF_DEBUG},
+ xml_pretty => 0,
+ log_slow_pages => 500,
);
-TUWF::register(
- qr// => \&home,
- qr{info/about} => \&about,
- qr{browse/search} => \&browsesearch,
-
- # These have to go before the other mappings, to ensure that links work for
- # man pages called 'pkg' or 'man'. This also means that we can't have a
- # system named 8 hex digits, but at least that's easy to guarantee. :)
- qr{([^/]+)/([0-9a-f]{8})} => \&man,
- qr{([^/]+)/([0-9a-f]{8})/src} => \&src,
- # We don't have any other single-component paths
- qr{([^/]+)} => \&man,
-
- qr{pkg/([^/]+)} => \&pkg_list,
- # pkg/$system/$category/$name (/$version); $category may contain a slash, too.
- qr{pkg/([^/]+)/(.+)} => \&pkg_info,
-
- # Redirects for canonical URLs
- qr{man/([^/]+)/(.+)} => \&man_redir,
-
- # Redirects for old URLs.
- # /browse/<pkg> has been moved to /pkg/ with the package category added to the path
- qr{browse/([^/]+)} => sub { $_[0]->resRedirect("/pkg/$_[1]", 'perm'); },
- qr{browse/([^/]+)/([^/]+)(?:/([^/]+))?} => sub {
- my($self, $sys, $name, $ver) = @_;
- $sys = $self->{sysbyshort}{$sys};
- return $self->resNotFound if !$sys;
- my $pkgs = $self->dbPackageGet(sysid => $sys->{id}, name => $name, results => 1);
- return $self->resNotFound if !@$pkgs;
- $self->resRedirect("/pkg/$sys->{short}/$pkgs->[0]{category}/$name".($ver ? "/$ver" :''), 'perm');
- },
-
- # Redirect for a specific language for a man page.
- # I'm not a fan of this solution; might drop it in the future.
- qr{lang/([^/]+)/([^/]+)} => sub {
- my($s, $l, $n) = @_;
- $n = _normalizename($n);
- my($m, undef) = $s->dbManPrefName($n, language => $l);
- return $s->resNotFound if !$m;
- $s->resRedirect("/$m->{name}/".substr($m->{hash}, 0, 8), 'temp');
- },
-
- qr{xml/search\.xml} => \&xmlsearch,
- qr{json/tree\.json} => \&jsontree,
-);
+TUWF::hook before => sub {
+ if(tuwf->{_TUWF}{http}) {
+ if(tuwf->resFile("$ROOT/www", tuwf->reqPath)) {
+ tuwf->resHeader('Cache-Control' => 'max-age=31536000');
+ tuwf->done;
+ }
+ }
+};
-TUWF::run();
+# TODO: Add SQL::Interp support to TUWF directly, in some form.
+sub TUWF::Object::dbExeci { shift->dbExec(sql_interp @_) }
+sub TUWF::Object::dbVali { shift->dbVal (sql_interp @_) }
+sub TUWF::Object::dbRowi { shift->dbRow (sql_interp @_) }
+sub TUWF::Object::dbAlli { shift->dbAll (sql_interp @_) }
+sub TUWF::Object::dbPagei { shift->dbPage(shift, sql_interp @_) }
-sub home {
- my $self = shift;
- my $stats = $self->dbStats;
- my $fn = sub { local $_=shift; 1 while(s/(\d)(\d{3})($|,)/$1,$2/); $_ };
- $self->htmlHeader(title => 'Man Pages Archive');
- h1 'Man Pages Archive';
- p class => 'txt'; lit sprintf <<' _', map $fn->($stats->{$_}), qw|hashes mans files packages|;
- Indexing <b>%s</b> versions of <b>%s</b> manual pages found in <b>%s</b>
- files of <b>%s</b> packages.
- <br /><br />
- Manned.org aims to index all manual pages from a variety of systems, both
- old and new, and provides a convenient interface for looking up and viewing
- the various versions of each man page.
- <a href="/info/about">About manned.org &raquo;</a>
- _
- end;
-
- h2 'Browse the manuals';
- ul id => 'systems';
- my %sys;
- push @{$sys{$_->{name}}}, $_ for(@{$self->{systems}});
- for my $sys (sort keys %sys) {
- $sys = $sys{$sys};
- (my $img = $sys->[0]{short}) =~ s/^(.+)-.+$/$1/;
- li;
- a href => "/pkg/$sys->[0]{short}" if @$sys == 1;
- span style => "background-image: url('images/$img.png')", '';
- b $sys->[0]{name};
- if(@$sys > 1) {
- my $i = 0;
- for(reverse @$sys) {
- a href => "/pkg/$_->{short}", ++$i > 3 ? (class => 'hidden') : (), $_->{release};
- lit ' ';
- }
- a href => "#", class => 'more', 'more...' if $i > 3;
- }
- end 'a' if @$sys == 1;
- end;
- }
- end;
-
- h2 'Other sites';
- ul id => 'external';
- li; a href => 'http://man7.org/linux/man-pages/index.html', 'man7.org'; txt ' - Linux man pages from several upstream projects.'; end;
- li; a href => 'http://manpag.es/', 'ManPag.es'; txt ' - Man pages from several Linux distributions.'; end;
- li; a href => 'https://www.mankier.com/', 'ManKier'; txt ' - Fedora Rawhide + some manually imported man pages; Nicely formatted and with some unique features.'; end;
- li; a href => 'http://man.cx/', 'man.cx'; txt ' - Man pages extracted from Debian testing.'; end;
- li; a href => 'http://man.he.net/', 'man.he.net'; txt ' - Also seems to be from a Debian-like system.'; end;
- li; a href => 'http://linux.die.net/man/', 'die.net'; txt ' - Seems to be based on an RPM-based Linux distribution.'; end;
- li; a href => 'http://manpages.org/', 'manpages.org'; txt ' - Lots of mostly-nicely formatted man pages, no clue about source.'; end;
- li; a href => 'http://www.manpagez.com/', 'manpagez.com'; txt ' - Mac OS X, has some GTK-html and texinfo documentation as well.'; end;
- li; a href => 'https://jlk.fjfi.cvut.cz/arch/manpages/dev', 'Arch Linux Man Pages'; end;
- li; a href => 'https://manpages.debian.org/', 'Debian Man Pages'; end;
- li; a href => 'https://www.dragonflybsd.org/cgi/web-man', 'DragonFlyBSD Man Pages'; end;
- li; a href => 'http://www.freebsd.org/cgi/man.cgi', 'FreeBSD.org Man Pages'; end;
- li; a href => 'http://netbsd.gw.com/cgi-bin/man-cgi', 'NetBSD Man Pages'; end;
- li; a href => 'http://www.openbsd.org/cgi-bin/man.cgi', 'OpenBSD Man Pages'; end;
- li; a href => 'http://manpages.ubuntu.com/', 'Ubuntu Manuals'; end;
- li; a href => 'https://man.voidlinux.eu/', 'Void Linux manpages'; end;
- end;
- $self->htmlFooter;
+# Set the last modification time from a string in yyyy-mm-dd format.
+sub TUWF::Object::resLastMod {
+ my($s, $d) = @_;
+ return if $d !~ /^(\d{4})-(\d{2})-(\d{2})/;
+ my @t = gmtime timegm 0,0,0,$3,$2-1,$1;
+ $s->resHeader('Last-Modified', sprintf '%s, %02d %s %04d %02d:%02d:%02d GMT',
+ (qw|Sun Mon Tue Wed Thu Fri Sat|)[$t[6]], $t[3],
+ (qw|Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec|)[$t[4]],
+ $t[5]+1900, $t[2], $t[1], $t[0]);
}
-sub about {
- my $self = shift;
- $self->htmlHeader(title => 'About');
- h1 'About Manned.org';
- div id => 'about';
-
- h2 'Goal';
- p; lit <<' _';
- The state of online indices of manual pages used to be a sad one. Existing
- sites used to only offer you a single version of a man page: From one
- origin, and often only in a single language. Most didn't even tell you where
- the manual actually originated from, making it very hard to determine
- whether the manual you found actually applied to your situation and even
- harder to find a manual for a specific system. Additionally, some sites
- rendered the manuals in an unreadable way, didn't correctly handle special
- formatting - like tables - or didn't correctly display non-ASCII characters.
- <br /><br />
- Nowadays there are many good alternatives, but Manned.org was one of the
- sites created in order to improve situation. This site aims to index the
- manual pages from a variaty of systems, both old and new, and allows you to
- browse through the various versions of a manual page to find out how each
- system behaves. The manuals are stored in the database as UTF-8, and are
- passed through <a href="http://www.gnu.org/software/groff/">groff</a> to
- render them in (mostly) the same way as they are displayed in your terminal.
- <br /><br />
- This website is <a href="https://code.blicky.net/yorhel/manned">open
- source</a> (MIT licensed) and written in a combination of Perl and Rust. The
- entire PostgreSQL database is available for download (see "Database
- download" below).
- _
- end;
-
- h2 'URL format';
- lit <<' _';
- <p>You can link to specific packages and man pages with several URL formats.
- These URLs will keep working in the future, so you should not have to worry
- about eventual dead links.</p>
- <h3>Man pages</h3>
- <p>The following URLs are available to refer to an individual man page:</p>
- <dl>
- <dt><code>/&lt;name>/&lt;8-hex-digits></code></dt><dd>
- This is the permalink format for a specific man page (e.g. <a href="/ls/910be0ed">/ls/910be0ed</a>).</dd>
- <dt><code>/&lt;name>[.&lt;section>]</code></dt><dd>
- Will try to get the latest and most-close-to-upstream version of a man
- page (e.g. <a href="/socket">/socket</a> or <a
- href="/socket.7">/socket.7</a>). Note that this may fetch the man page
- from any available system, so may result in confusing scenarios for
- system-specific documentation.</dd>
- <dt><code>/man/&lt;system>/&lt;name>[.&lt;section>]</code></dt><dd>
- Will get the latest version of a man page from the given system (e.g. <a
- href="/man/ubuntu-xenial/rsync">/man/ubuntu-xenial/rsync</a>)</dd>
- <dt><code>/man/&lt;system>/&lt;category>/&lt;package>/&lt;name>[.&lt;section>]</code></dt><dd>
- Will get the latest version of a man page from the given package (e.g. <a
- href="/man/ubuntu-xenial/net/rsync/rsync">/man/ubuntu-xenial/net/rsync/rsync</a>)</dd>
- <dt><code>/man/&lt;system>/&lt;category>/&lt;package>/&lt;version>/&lt;name>[.&lt;section>]</code></dt><dd>
- Will get the man page from a specific package version (e.g. <a
- href="/man/ubuntu-xenial/net/rsync/3.1.1-3ubuntu1/rsync">/man/ubuntu-xenial/net/rsync/3.1.1-3ubuntu1/rsync</a>)</dd>
- </dl>
- <p>Currently, the last three URLs will perform a redirect to the
- appropriate permalink URL, but this may change in the future.<br />
- In all URLs where an optional <code>.&lt;section></code> can be provided,
- the search is performed as a prefix match. For example, <a
- href="/cat.3">/cat.3</a> will provide the <code>cat.3tcl</code> man page if
- no exact <code>cat.3</code> version is available. Linking to the full
- section name is also possible: <a href="/cat.3tcl">/cat.3tcl</a>. If no
- section is given and multiple sections are available, the lowest section
- number is chosen.</p>
- <h3>Packages</h3>
- <p>Linking to individual packages is also possible. These pages will show a
- listing of all manual pages available in the given package.</p>
- <dl>
- <dt><code>/pkg/&lt;system>/&lt;category>/&lt;package></code></dt><dd>
- For the latest version of a package (e.g. <a
- href="/pkg/arch/core/coreutils">/pkg/arch/core/coreutils</a>).</dd>
- <dt><code>/pkg/&lt;system>/&lt;category>/&lt;package>/&lt;version></code></dt><dd>
- For a particular version of a package (e.g. <a
- href="/pkg/arch/core/coreutils/8.25-2">/pkg/arch/core/coreutils/8.25-2</a>).</dd>
- </dl>
- <p>Note that this site only indexes packages that actually have manual
- pages; Linking to a package that doesn't have any will result in a 404
- page.</p>
- _
-
- h2 'The indexing process';
- p; lit <<' _';
- All man pages are fetched right from the (binary) packages available on the
- public repositories of Linux distributions. In particular:<br />
- <dl>
- <dt>Arch Linux</dt><dd>
- The core, extra and community repositories are fetched from a local
- Arch mirror. Indexing started around begin June 2012. The i686
- architecture was indexed until November 6th, 2016, packages after that
- were fetched from from x86_64.</dd>
- <dt>Debian</dt><dd>
- Historical releases were fetched from <a
- href="http://archive.debian.org/debian/">http://archive.debian.org/debian/</a>
- and <a href="http://snapshot.debian.org/">http://snapshot.debian.org/</a>.
- For buzz, rex and bo, we're missing a few man pages because some packages
- were missing from the repository archives. Where available, all components
- (main, contrib and non-free) from the $release and $release-updates
- repositories are indexed.</dd>
- <dt>CentOS</dt><dd>
- Historical releases were fetched from <a
- href="http://vault.centos.org/">vault.centos.org</a>, current releases
- from a local mirror. Where applicable, the following repositories were
- indexed: addons, centosplus, contrib, extras, os. The i386 architecture
- was indexed for versions lower than 7.0, since 7.0 the packages from
- x86_64 are indexed.
- <dt>Fedora</dt><dd>
- Historical releases were fetched from <a
- href="http://archives.fedoraproject.org/pub/archive/fedora/linux/">archives.fedoraproject.org</a>,
- current releases from a local repository. Fedora Core 1 till 6 are
- (incorrectly) called 'Fedora' here. To compensate for that, Fedora 3 till
- 6 also include the Extras repository. For Fedora 7 and later, the
- 'Everything' and 'updates' repositories are indexed. The i386 arch was
- indexed for Fedora 17 and older, the x86_64 arch starting with Fedora
- 18.</dd>
- <dt>FreeBSD</dt><dd>
- Historical releases were fetched from <a
- href="http://ftp-archive.freebsd.org/mirror/FreeBSD-Archive/">http://ftp-archive.freebsd.org/mirror/FreeBSD-Archive/</a>.
- The base installation tarballs are included in the database as packages
- prefixed with <i>core-</i>. The package repositories have also been
- indexed, except for 2.0.5 - 2.2.7 and 3.0 - 3.3 because those were not
- available on the ftp archive. Only the -RELEASE repositories have been
- included, which is generally a snapshot of the ports directory around the
- time of the release. The release dates indicated for many packages were
- guessed from the file modification dates in the tarball, and may be
- inaccurate. The i368 arch was indexed for FreeBSD 11.0 and older, the
- amd64 arch starting with 11.1.</dd>
- <dt>Ubuntu</dt><dd>
- Historical releases were fetched from <a
- href="http://old-releases.ubuntu.com/ubuntu/">http://old-releases.ubuntu.com/ubuntu/</a>,
- supported releases from a local mirror. All components (main, universe,
- restricted and multiverse) from the $release, $release-updates and
- $release-security repositories are indexed. Indexing started around mid
- June 2012. All releases before 2017 were indexed from the i386
- repositories, starting with 17.04 the amd64 repositories were used.</dd>
- </dl>
- <p>
- Only packages for a single architecture (i386 or amd64) are scanned. To my
- knowledge, packages that come with different manuals for different
- architectures either don't exist or are extremely rare. It does happen that
- some packages are not available for all architectures. Usually, though,
- every package is at least available for the most popular architecture, so
- hopefully we're not missing out on much. <br /><br />
- The repositories are scanned for new packages on a daily basis.
- </p>
- _
- end;
-
- h2 'Database download';
- p; lit <<' _';
- This site is backed by a PostgreSQL database containing all the man pages.
- Weekly dumps of the full database are available for download at
- <a href="http://dl.manned.org/dumps/">http://dl.manned.org/dumps/</a>.
- <br /><br />
- Be warned that the download server may not be terribly reliable, so it is
- advisable to use a client that supports resumption of partial downloads. See
- <a href="/wget">wget's -c</a> or <a href="/curl">curl's -C</a>.
- <br /><br />
- The database schema is "documented" at <a
- href="https://code.blicky.net/yorhel/manned/src/branch/master/sql/schema.sql">schema.sql</a>
- in the git repo. Note that these dumps don't constitute a stable API and,
- while this won't happen frequently, incompatible schema changes or Postgres
- major version bumps may occur.
- _
- end;
-
- h2 'Other systems';
- p; lit <<' _';
- Suggestions for new (or old) systems to index are welcome.
- <br /><br />
- It would be great to index a few more non-Linux systems such as other BSDs,
- Solaris/Illumos and Mac OS X. Unfortunately, those don't always follow a
- binary package based approach, or are otherwise less easy to properly index.
- <br /><br />
- In general, systems that follow an entirely source-based distribution
- approach can't be indexed without compiling everything. Since that is both
- very resource-heavy and open to security issues, there are no plans to
- include manuals from such systems at the moment. So unless someone comes
- with a solution I hadn't thought of yet, there won't be any Gentoo manuals
- here. :-(
- _
- end;
-
- h2 'Future plans';
- p; lit <<' _';
- This site isn't nearly as awesome yet as it could be. Here's some ideas that
- would be nice to have in the future:
- <ul>
- <li>Improved, more intelligent, search,</li>
- <li><a href="/apropos.1">apropos(1)</a> emulation(?),</li>
- <li>Diffs between various versions of a man page,</li>
- <li>Anchor links within man pages, for easier linking to a section or paragraph,</li>
- <li>Alternative formats (Text, PDF, more semantic HTML, etc),</li>
- <li>A command-line client, like <a href="/man.1">man(1)</a> with manned.org as database backend.</li>
- </ul>
- _
- end;
-
- h2 'Copyright';
- p; lit <<' _';
- All manual pages are copyrighted by their respective authors. The manuals
- have been fetched from publically available repositories of free and
- (primarily) open source software. The distributors of said software have put
- in efforts to only include software and documentation that allows free
- distribution. Nonetheless, if a manual that does not allow to be
- redistributed has been inadvertently included in our index, please let me
- know and I will have it removed as soon as possible.
- _
- end;
-
- end;
- $self->htmlFooter;
+# The systems table doesn't change often, so keep an in-memory cache for quick lookups.
+sub systems {
+ state $s ||= [ map {
+ $_->{full} = $_->{name}.($_->{release}?' '.$_->{release}:'');
+ $_
+ } tuwf->dbAll('SELECT id, name, release, short FROM systems ORDER BY name, id')->@* ];
}
+sub sysbyid { state $s ||= { map +($_->{id}, $_), systems->@* } }
+sub sysbyshort { state $s ||= { map +($_->{short}, $_), systems->@* } }
-sub paginate {
- my($url, $count, $perpage, $p) = @_;
- return if $count <= $perpage;
-
- my $l = sub {
- my $c = shift;
- a href => sprintf('%s%d', $url, $c), $c if $c != $p;
- b $c if $c == $p;
- };
-
- my $lp = ceil($count/$perpage);
- p class => 'paginate';
- $l->(1) if $p > 1+4;
- b '...' if $p > 1+5;
- $l->($_) for (($p > 4 ? $p-4 : 1)..($p+4 > $lp ? $lp : $p+4));
- b '...' if $p < $lp-5;
- $l->($lp) if $p < $lp-4;
- end;
-}
+# URL-unescape some special characters that may occur in man names.
+# Firefox seems to escape [ and ] in URLs. It doesn't really have to...
+sub normalize_name { $_[0] =~ s/%5b/[/irg =~ s/%5d/]/irg =~ s/%20/ /rg }
+sub shorthash_to_hex { unpack 'H*', pack 'i', $_[0] } # int -> hex
+sub shorthash_to_int { unpack 'i', pack 'H*', $_[0] } # hex -> int
-sub browsesearch {
- my $self = shift;
- my $q = $self->reqGet('q')||'';
- my $man = $self->dbSearch($q, 150);
-
- return $self->resRedirect("/$man->[0]{name}.$man->[0]{section}", 'temp') if @$man == 1;
-
- $self->htmlHeader(title => 'Search results for '.$q);
- h1 'Search results for '.$q;
- p 'Note: This is just a simple case-insensitive prefix match on the man names. In the future we\'ll have more powerful search functionality. Hopefully.';
- if(@$man) {
- ul id => 'searchres';
- for(@$man) {
- li;
- a href => "/$_->{name}.$_->{section}", $_->{name};
- i " $_->{section}";
- end;
- }
- end;
- } else {
- br; br;
- b 'No results :-(';
- }
-
- $self->htmlFooter;
-}
+# Subquery returning all packages that have a man page.
+my $packages_with_man = '(SELECT * FROM packages p WHERE EXISTS(SELECT 1 FROM package_versions pv WHERE pv.package = p.id AND EXISTS(SELECT 1 FROM files f WHERE f.pkgver = pv.id)))';
+sub escape_like { $_[0] =~ s/([_%\\])/\\$1/rg }
-sub pkg_list {
- my($self, $short) = @_;
+sub sql_join {
+ my $sep = shift;
+ my @args = map +($sep, $_), @_;
+ sql @args[1..$#args];
+}
+sub sql_and { @_ ? sql_join 'AND', map sql('(', $_, ')'), @_ : sql '1=1' }
+sub sql_or { @_ ? sql_join 'OR', map sql('(', $_, ')'), @_ : sql '1=0' }
- my $sys = $self->{sysbyshort}{$short};
- return $self->resNotFound if !$sys;
- my $f = $self->formValidate(
- { get => 'c', required => 0, enum => [ '0', 'all', 'a'..'z' ], default => 'all' },
- { get => 'p', required => 0, default => 1, template => 'uint', min => 1, max => 200 },
- );
- return $self->resNotFound if $f->{_err};
+sub pkg_frompath {
+ my($sys_where, $path) = @_;
- my %opt = (hasman => 1, sysid => $sys->{id}, char => $f->{c} eq 'all' ? undef : $f->{c});
- my $pkg = $self->dbPackageGet(%opt, results => 200, page => $f->{p});
- my $count = $self->dbPackageGet(%opt, countonly => 1)->[0]{count};
+ # $path should be "$category/$name" or "$category/$name/$version", since
+ # $category may contain a slash, let's try both options.
- my $title = "Packages for $sys->{name}".($sys->{release}?" $sys->{release}":"");
- $self->htmlHeader(title => $title);
- div id => 'pkglist';
- h1 $title;
+ my sub lookup {
+ my($cat, $name) = @_;
+ tuwf->dbRowi('SELECT id, system, name, category FROM', $packages_with_man, 'p WHERE', $sys_where, 'AND category =', \$cat, 'AND name =', \$name);
+ }
- p class => 'charselect';
- for('all', 0, 'a'..'z') {
- a href => "/pkg/$short?c=$_", $_?uc$_:'#' if $_ ne $f->{c};
- b $_?uc$_:'#' if $_ eq $f->{c};
+ # $category/$name
+ # e.g. contrib/games/alien
+ if($path =~ m{^(.+)/([^/]+)$}) {
+ my $pkg = lookup $1, $2;
+ return ($pkg, '') if $pkg->{id};
}
- end;
-
- p 'Note: Packages without man pages are not listed.';
- paginate "/pkg/$short?c=$f->{c};p=", $count, 200, $f->{p};
- ul id => 'packages';
- for(@$pkg) {
- li;
- a href => "/pkg/$short/$_->{category}/$_->{name}", $_->{name};
- i ' '.$_->{category};
- end;
+
+ # $category/$name/$version
+ # e.g. contrib/games/alien/10.2
+ if($path =~ m{^(.+)/([^/]+)/([^/]+)$}) {
+ my $pkg = lookup $1, $2;
+ return ($pkg, $3) if $pkg->{id};
}
- end;
- paginate "/pkg/$short?c=$f->{c};p=", $count, 200, $f->{p};
- end;
- $self->htmlFooter;
+ (undef, '');
}
-sub pkg_frompath {
- my($self, $sys, $path) = @_;
-
- # $path should be "$category/$name" or "$category/$name/$version", since
- # $category may contain a slash, let's try both options.
-
- # $category/$name
- # e.g. contrib/games/alien
- if($path =~ m{^(.+)/([^/]+)$}) {
- my($category, $name) = ($1, $2);
- my $pkg = $self->dbPackageGet(sysid => $sys, category => $category, name => $name, hasman => 1)->[0];
- return ($pkg, '') if $pkg;
- }
-
- # $category/$name/$version
- # e.g. contrib/games/alien/10.2
- if($path =~ m{^(.+)/([^/]+)/([^/]+)$}) {
- my($category, $name, $version) = ($1, $2, $3);
- my $pkg = $self->dbPackageGet(sysid => $sys, category => $category, name => $name, hasman => 1)->[0];
- return ($pkg, $version) if $pkg;
- }
-
- (undef, '');
+# Get the preferred man page for the given filters.
+sub man_pref {
+ my($section, $where) = @_;
+ $where = sql_and $where, sql 'm.section LIKE', \(escape_like($section).'%') if length $section;
+
+ # Criteria to determine a "preferred" man page:
+ # 1. english: English versions of a man page have preference over other locales
+ # 2. pkgver: Newer versions of the same package have preference over older versions
+ # 3. stdloc: Prefer man pages in standard locations
+ # 4. secmatch: Prefer an exact section match
+ # 5. arch: Prefer Arch over other systems (because it tends to be the most up-to-date, and closest to upstreams)
+ # 6. debian: If there's no Arch, prefer latest Debian over other systems (again, tends to be more up-to-date)
+ # (also resolves distro-specific tooling disputes such as https://code.blicky.net/yorhel/manned/issues/1 )
+ # 7. sysrel: Prefer a more recent system release over an older release
+ # 8. secorder: Lower sections before higher sections (because man does it this way, for some reason)
+ # 9. pkgdate: Prefer more recent packages (cross-distro)
+ # 10. Fall back on shorthash comparison, to ensure the result is stable
+
+ state $archid = sysbyshort->{arch}{id};
+ state $debid = (sort { $b->{id} <=> $a->{id} } grep $_->{short} =~ /^debian-/, systems->@*)[0]{id};
+
+ tuwf->dbRowi(q{
+ WITH unfiltered AS (
+ SELECT m.name, m.section, l.locale, f.shorthash, f.content, f.filename, s AS sys, p AS pkg, v AS ver
+ FROM files f
+ JOIN locales l ON l.id = f.locale
+ JOIN mans m ON m.id = f.man
+ JOIN package_versions v ON v.id = f.pkgver
+ JOIN packages p ON p.id = v.package
+ JOIN systems s ON s.id = p.system
+ WHERE}, $where, q{
+ ), f_english AS(
+ SELECT * FROM unfiltered WHERE NOT EXISTS(SELECT 1 FROM unfiltered WHERE is_english_locale(locale)) OR is_english_locale(locale)
+ ), f_pkgver AS(
+ SELECT * FROM f_english a WHERE NOT EXISTS(SELECT 1 FROM f_english b WHERE (a.ver).package = (b.ver).package AND (a.ver).released < (b.ver).released)
+ ), f_stdloc AS(
+ SELECT * FROM f_pkgver WHERE NOT EXISTS(SELECT 1 FROM f_pkgver WHERE is_standard_man_location(filename)) OR is_standard_man_location(filename)
+ ), f_secmatch AS(
+ SELECT * FROM f_stdloc WHERE NOT EXISTS(SELECT 1 FROM f_stdloc WHERE section =}, \$section, q{) OR section =}, \$section, q{
+ ), f_arch AS(
+ SELECT * FROM f_secmatch WHERE NOT EXISTS(SELECT 1 FROM}, length $section ? 'f_secmatch' : 'f_stdloc', qq{WHERE (sys).id = $archid) OR (sys).id = $archid
+ ), f_debian AS(
+ SELECT * FROM f_arch WHERE NOT EXISTS(SELECT 1 FROM f_arch WHERE (sys).id = $debid) OR (sys).id = $debid
+ ), f_sysrel AS(
+ SELECT * FROM f_debian a WHERE NOT EXISTS(SELECT 1 FROM f_debian b WHERE (a.sys).name = (b.sys).name AND (a.sys).id < (b.sys).id)
+ ), f_secorder AS(
+ SELECT * FROM f_sysrel a WHERE NOT EXISTS(SELECT 1 FROM f_sysrel b WHERE a.section > b.section)
+ ), f_pkgdate AS(
+ SELECT * FROM f_secorder a WHERE NOT EXISTS(SELECT 1 FROM f_secorder b WHERE (a.ver).released < (b.ver).released)
+ )
+ SELECT (pkg).system, (pkg).category, (pkg).name AS package, (ver).version, (ver).released, (ver).id AS verid,
+ name, section, filename, locale, shorthash, content
+ FROM f_pkgdate ORDER BY shorthash LIMIT 1
+ });
}
-sub pkg_info {
- my($self, $short, $path) = @_;
-
- my $sys = $self->{sysbyshort}{$short};
- return $self->resNotFound if !$sys;
-
- my($pkg, $ver) = pkg_frompath($self, $sys->{id}, $path);
- return $self->resNotFound if !$pkg;
+# Given the name of a man page with optional section, find out the actual name
+# and section suffix of the man page and the preferred version.
+sub man_pref_name {
+ my($name, $where) = @_;
+
+ # Check the <name>.<section> format first, because ~most~ cases where
+ # there's a collision in the format, the <name>-only page is either
+ # uninteresting or a file name parsing error.
+ if ($name =~ /^(.+)\.([^.]+)$/) {
+ my($n, $s) = ($1,$2);
+ my $man = man_pref $s, sql_and $where, sql 'm.name =', \$n;
+ return ($man, $s) if length $man->{name};
+ }
- my $vers = $self->dbPackageVersions($pkg->{id});
+ my $man = man_pref undef, sql_and $where, sql 'm.name =', \$name;
+ length $man->{name} ? ($man, '') : (undef, '');
+}
- my $sel = $ver ? (grep $_->{version} eq $ver, @$vers)[0] : $vers->[0];
- return $self->resNotFound if !$sel;
- my $f = $self->formValidate({ get => 'p', required => 0, default => 1, template => 'uint', min => 1, max => 100});
- return $self->resNotFound if $f->{_err};
+sub framework_ {
+ my $content = pop;
+ my(%o) = @_;
+
+ html_ lang => 'en', sub {
+ head_ sub {
+ link_ rel => 'stylesheet', type => 'text/css', href => '/man.css?5';
+ title_ $o{title}.' - manned.org';
+ };
+ body_ sub {
+ header_ sub {
+ a_ href => '/', 'Manned.org';
+ form_ action => '/browse/search', method => 'get', sub {
+ input_ type => 'text', name => 'q', id => 'q', tabindex => 1;
+ input_ type => 'submit', value => 'Search';
+ }
+ };
+ main_ class => $o{mainclass}, $content;
+ footer_ sub {
+ span_ sub {
+ a_ href => '/info/about', 'about'; txt_ ' | ';
+ a_ href => 'mailto:manned@yorhel.nl', 'contact'; txt_ ' | ';
+ a_ href => 'https://code.blicky.net/yorhel/manned', 'source';
+ };
+ span_ 'all manual pages are copyrighted by their respective authors.';
+ };
+ script_ type => 'text/javascript', src => '/man.js', '';
+ }
+ };
+
+ # write the SQL queries as a HTML comment when debugging is enabled
+ # (stolen from VNDB code)
+ # (TODO: Move this into TUWF or something)
+ if(tuwf->debug) {
+ my(@sql_r, @sql_i) = ();
+ for (tuwf->{_TUWF}{DB}{queries}->@*) {
+ my($sql, $params, $time) = @$_;
+ my @params = sort { $a =~ /^[0-9]+$/ && $b =~ /^[0-9]+$/ ? $a <=> $b : $a cmp $b } keys %$params;
+ my $prefix = sprintf " [%6.2fms] ", $time*1000;
+ push @sql_r, sprintf "%s%s | %s", $prefix, $sql, join ', ', map "$_:".DBI::neat($params->{$_}), @params;
+ my $i=1;
+ push @sql_i, $prefix.($sql =~ s/\?/tuwf->dbh->quote($params->{$i++})/egr);
+ }
+ my $sql_r = join "\n", @sql_r;
+ my $sql_i = join "\n", @sql_i;
+ my $modules = join "\n", sort keys %INC;
+ lit_ "\n<!--\nSQL (with placeholders):\n$sql_r\n\nSQL (interpolated, possibly buggy):\n$sql_i\n\nMODULES:\n$modules\n-->";
+ }
+}
- my $mans = $self->dbManInfo(package => $sel->{id}, results => 200, page => $f->{p}, sort => 'syspkgname');
- my $count = $self->dbManInfo(package => $sel->{id}, countonly => 1)->[0]{count};
- # Latest version of this package determines last modification date of the page.
- $self->setLastMod($vers->[0]{released});
+sub paginate_ {
+ my($url, $count, $perpage, $p) = @_;
+ return if $count <= $perpage;
- my $title = "$sys->{name}".($sys->{release}?" $sys->{release}":"")." / $pkg->{category} / $pkg->{name}";
- $self->htmlHeader(title => "$title $sel->{version}");
- h1 $title;
+ my sub l_ {
+ my($c)= @_;
+ a_ href => "$url$c", $c if $c != $p;
+ b_ $c if $c == $p;
+ };
- div id => 'pkgversions';
- h2 'Versions';
- ul;
- for(@$vers) {
- li;
- a href => "/pkg/$sys->{short}/$pkg->{category}/$pkg->{name}/$_->{version}", $_->{version} if $_ != $sel;
- b " $_->{version}" if $_ == $sel;
- i " $_->{released}";
- end;
- }
- end;
- end;
-
- div id => 'pkgmans';
- h2 "Manuals for version $sel->{version}";
- paginate "/pkg/$sys->{short}/$pkg->{category}/$pkg->{name}/$sel->{version}?p=", $count, 200, $f->{p};
- ul;
- for(@$mans) {
- li;
- a href => "/$_->{name}/".substr($_->{hash},0,8), "$_->{name}($_->{section})";
- b " $_->{locale}" if $_->{locale};
- i " $_->{filename}";
- end;
+ my $lp = ceil($count/$perpage);
+ nav_ class => 'paginate', sub {
+ l_ 1 if $p > 1+4;
+ b_ '...' if $p > 1+5;
+ l_ $_ for (($p > 4 ? $p-4 : 1)..($p+4 > $lp ? $lp : $p+4));
+ b_ '...' if $p < $lp-5;
+ l_ $lp if $p < $lp-4;
}
- end;
- paginate "/pkg/$sys->{short}/$pkg->{category}/$pkg->{name}/$sel->{version}?p=", $count, 200, $f->{p};
- end;
-
- $self->htmlFooter;
}
-sub man_redir {
- my($self, $sys, $path) = @_;
+TUWF::set error_404_handler => sub {
+ tuwf->resStatus(404);
+ my $title = 'No manual entry for '.tuwf->reqPath;
+ framework_ title => $title, sub {
+ h1_ $title;
+ p_ 'That is, the page you were looking for doesn\'t exist.';
+ };
+};
- # Path can be:
- # 1. <name>
- # 2. <category>/<package>/<name>
- # 3. <category>/<package>/<version>/<name>
- $sys = $self->{sysbyshort}{$sys};
- return $self->resNotFound if !$sys;
+TUWF::get '/' => sub {
+ my $stats = tuwf->dbRow('SELECT * FROM stats_cache');
+
+ sub num { local $_=shift; 1 while(s/(\d)(\d{3})($|,)/$1,$2/); $_ };
+
+ framework_ title => 'Man Pages Archive', mainclass => 'thin', sub {
+ h1_ 'Welcome to Manned.org';
+ h2_ 'The archive for man pages';
+ lit sprintf <<' _', map num($stats->{$_}), qw|hashes mans files packages|;
+ <p>
+ Indexing <b>%s</b> versions of <b>%s</b> manual pages found in
+ <b>%s</b> files of <b>%s</b> packages.
+ </p><p>
+ Manned.org aims to index all manual pages from a variety of systems, both
+ old and new, and provides a convenient interface for looking up and viewing
+ the various versions of each man page.
+ <a href="/info/about">More information &raquo;</a>
+ </p>
+ _
+
+ h2_ 'Indexed systems';
+ div_ class => 'systems', sub {
+ my %sys;
+ push $sys{$_->{name}}->@*, $_ for systems->@*;
+ div_ sub {
+ my $sys = $sys{$_};
+ my $img = $sys->[0]{short} =~ s/^(.+)-.+$/$1/r;
+ if(@$sys == 1) {
+ a_ href => "/pkg/$sys->[0]{short}", sub {
+ img_ width => 50, height => 50, src => "images/$img.png";
+ b_ $sys->[0]{name};
+ };
+ return;
+ }
+ img_ width => 50, height => 50, src => "images/$img.png";
+ div_ sub {
+ b_ $sys->[0]{name};
+ for(reverse @$sys) {
+ a_ href => "/pkg/$_->{short}", $_->{release};
+ lit_ ' ';
+ }
+ };
+ } for sort keys %sys;
+ };
+
+ h2_ 'Other relevant sites';
+ ul_ sub {
+ li_ sub { a_ href => 'http://man7.org/linux/man-pages/index.html', 'man7.org'; txt_ ' - Linux man pages from several upstream projects.' };
+ li_ sub { a_ href => 'https://manpag.es/', 'ManPag.es'; txt_ ' - Man pages from several Linux distributions.' };
+ li_ sub { a_ href => 'https://www.mankier.com/', 'ManKier'; txt_ ' - Fedora Rawhide + some manually imported man pages; Nicely formatted and with some unique features.' };
+ li_ sub { a_ href => 'https://man.cx/', 'man.cx'; txt_ ' - Man pages extracted from Debian testing.' };
+ li_ sub { a_ href => 'http://man.he.net/', 'man.he.net'; txt_ ' - Also seems to be from a Debian-like system.' };
+ li_ sub { a_ href => 'https://linux.die.net/man/', 'die.net'; txt_ ' - Seems to be based on an RPM-based Linux distribution.' };
+ li_ sub { a_ href => 'http://manpages.org/', 'manpages.org'; txt_ ' - Lots of mostly-nicely formatted man pages, no clue about source.' };
+ li_ sub { a_ href => 'https://www.manpagez.com/', 'manpagez.com'; txt_ ' - Mac OS X, has some GTK-html and texinfo documentation as well.' };
+ li_ sub { a_ href => 'https://man.archlinux.org/', 'Arch Linux Man Pages' };
+ li_ sub { a_ href => 'https://manpages.debian.org/', 'Debian Man Pages' };
+ li_ sub { a_ href => 'https://www.dragonflybsd.org/cgi/web-man', 'DragonFlyBSD Man Pages' };
+ li_ sub { a_ href => 'https://www.freebsd.org/cgi/man.cgi', 'FreeBSD.org Man Pages' };
+ li_ sub { a_ href => 'https://man.netbsd.org/', 'NetBSD Man Pages' };
+ li_ sub { a_ href => 'https://www.openbsd.org/cgi-bin/man.cgi', 'OpenBSD Man Pages' };
+ li_ sub { a_ href => 'https://manpages.ubuntu.com/', 'Ubuntu Manuals' };
+ li_ sub { a_ href => 'https://man.voidlinux.org/', 'Void Linux manpages' };
+ };
+ };
+};
- my $man;
- if($path !~ m{/}) { # (1)
- ($man) = $self->dbManPrefName($path, sysid => $sys->{id});
- } else {
- $path =~ s{/([^/]+)$}{};
- my $name = $1;
+TUWF::get '/info/about' => sub {
+ framework_ title => 'About', mainclass => 'thin', sub {
+ h1_ 'About Manned.org';
+ lit <<' _';
+ <h2 id="goal">Goal</h2>
+ <p>
+ The state of online indices of manual pages used to be a sad one. Existing
+ sites used to only offer you a single version of a man page: From one
+ origin, and often only in a single language. Most didn't even tell you
+ where the manual actually originated from, making it very hard to
+ determine whether the manual you found applied to your situation and even
+ harder to find a manual for a specific system. Additionally, some sites
+ rendered the manuals in an unreadable way, didn't correctly handle special
+ formatting - like tables - or didn't correctly display non-ASCII
+ characters.
+ </p><p>
+ Nowadays there are many good alternatives, but Manned.org was one of the
+ sites created in order to improve that situation. This site aims to index
+ the manual pages from a variaty of systems, both old and new, and allows you
+ to browse through the various versions of a manual page to find out how each
+ system behaves. The manuals are stored in the database as UTF-8, and are
+ passed through <a href="http://www.gnu.org/software/groff/">groff</a> to
+ render them in (mostly) the same way as they are displayed in your terminal.
+ </p><p>
+ This website is <a href="https://code.blicky.net/yorhel/manned">open
+ source</a> (AGPL licensed) and written in a combination of Perl and Rust.
+ The entire PostgreSQL database is available
+ <a href="#database-download">for download</a>.
+ </p>
+
+ <h2 id="url-format">URL format</h2>
+ <p>You can link to specific packages and man pages with several URL formats.
+ These URLs will keep working in the future, so you should not have to worry
+ about eventual dead links.</p>
+ <h3>Man pages</h3>
+ <p>The following URLs are available to refer to an individual man page:</p>
+ <dl>
+ <dt><code>/&lt;name>[.&lt;section>]</code> or <code>/man/&lt;name>[.&lt;section>]</code></dt><dd>
+ Will try to get the latest and most-close-to-upstream version of a man
+ page. Note that this will fetch the man page from any of the available
+ systems, so may result in confusing scenarios for system-specific
+ documentation. I try to at least keep the selection algorithm stable and
+ deterministic, but can't provide any guarantees. Examples:<br>
+ <a href="/socket">/socket</a><br>
+ <a href="/socket.7">/socket.7</a><br>
+ <a href="/man/socket.7">/man/socket.7</a></dd>
+ <dt><code>/man/&lt;system>/&lt;name>[.&lt;section>]</code></dt><dd>
+ Will get the latest version of a man page from the given system, e.g.:<br>
+ <a href="/man/ubuntu/rsync">/man/ubuntu/rsync</a><br>
+ <a href="/man/ubuntu-xenial/rsync">/man/ubuntu-xenial/rsync</a></dd>
+ <dt><code>/man/&lt;system>/&lt;category>/&lt;package>/&lt;name>[.&lt;section>]</code></dt><dd>
+ Will get the latest version of a man page from the given package, e.g.:<br>
+ <a href="/man/ubuntu-xenial/net/rsync/rsync">/man/ubuntu-xenial/net/rsync/rsync</a></dd>
+ <dt><code>/man/&lt;system>/&lt;category>/&lt;package>/&lt;version>/&lt;name>[.&lt;section>]</code></dt><dd>
+ Will get the man page from a specific package version, e.g.:<br>
+ <a href="/man/ubuntu-xenial/net/rsync/3.1.1-3ubuntu1/rsync">/man/ubuntu-xenial/net/rsync/3.1.1-3ubuntu1/rsync</a></dd>
+ <dt><code>/man.&lt;language>/...</code></dt><dd>
+ Adding a language code to the <code>/man/</code> component will select
+ the man page in the requested language. The man page has to be available
+ in that language, otherwise you will get a 404. Redirects to other
+ languages as fallback may be implemented in the future. English man
+ pages are typically not tagged with a language at all, so explicitely
+ requesting <code>/man.en/...</code> will usually fail. This, too, may be
+ improved in the future. Examples:<br>
+ <a href="/man.de/faked-tcp">/man.de/faked-tcp</a><br>
+ <a href="/man.fr/fedora/rsync.1">/man.de/fedora/rsync.1</a></dd>
+ <dt><code>/man.&lt;8-hex-digits>/...</code></dt><dd>
+ Permalink format. Adding the shorthash of the man page to the
+ <code>/man/</code> component of the above URLs will get that specific
+ man page from the requested system and/or package. The contents of the
+ man page should generally be the same regardless of which system or
+ package is included in the URL, but the UI may provide a different
+ nagivation context. Examples:<br>
+ <a href="/man.910be0ed/ls">/man.910be0ed/ls</a><br>
+ <a href="/man.910be0ed/fedora/ls">/man.910be0ed/fedora/ls</a><br>
+ <a href="/man.910be0ed/arch/ls">/man.910be0ed/arch/ls</a><br>
+ <a href="/man.910be0ed/fedora/everything/coreutils-common/ls">/man.910be0ed/fedora/everything/coreutils-common/ls</a></dd>
+ <dt><code>/raw...</code></dt><dd>
+ In all of the above URL formats, you can change <code>/man</code> with
+ <code>/raw</code> to get the raw UTF-8 encoded man page source, e.g.:<br>
+ <a href="/raw/socket.7">/raw/socket.7</a><br>
+ <a href="/raw/ubuntu-xenial/net/rsync/3.1.1-3ubuntu1/rsync">/raw/ubuntu-xenial/net/rsync/3.1.1-3ubuntu1/rsync</a><br>
+ <a href="/raw.de/faked-tcp">/raw.de/faked-tcp</a><br>
+ <a href="/raw.910be0ed/fedora/ls">/raw.910be0ed/fedora/ls</a></dd>
+ <dt><code>/&lt;name>/&lt;8-hex-digits></code></dt><dd>
+ Old permalink format for a specific man page (e.g. <a href="/ls/910be0ed">/ls/910be0ed</a>).</dd>
+ </dl>
+ <p>In all URLs where an optional <code>.&lt;section></code> can be provided,
+ the search is performed as a prefix match. For example, <a
+ href="/cat.3">/cat.3</a> will provide the <code>cat.3tcl</code> man page if
+ no exact <code>cat.3</code> version is available. Linking to the full
+ section name is also possible: <a href="/cat.3tcl">/cat.3tcl</a>. If no
+ section is given and multiple sections are available, the lowest section
+ number is chosen.</p>
+ <h3>Packages</h3>
+ <p>Linking to individual packages is also possible. These pages will show a
+ listing of all manual pages available in the given package.</p>
+ <dl>
+ <dt><code>/pkg/&lt;system>/&lt;category>/&lt;package></code></dt><dd>
+ For the latest version of a package (e.g. <a
+ href="/pkg/arch/core/coreutils">/pkg/arch/core/coreutils</a>).</dd>
+ <dt><code>/pkg/&lt;system>/&lt;category>/&lt;package>/&lt;version></code></dt><dd>
+ For a particular version of a package (e.g. <a
+ href="/pkg/arch/core/coreutils/8.25-2">/pkg/arch/core/coreutils/8.25-2</a>).</dd>
+ </dl>
+ <p>This site only indexes packages that actually have manual pages,
+ linking to a package that doesn't have any will result in a 404 page.</p>
+
+ <h2 id="indexing">The indexing process</h2>
+ <p>
+ All man pages are fetched right from the (binary) packages available on the
+ public repositories of Linux distributions. In particular:<br />
+ </p>
+ <dl>
+ <dt>Alpine Linux</dt><dd>
+ The main (since 3.0) and community (since 3.3) repositories are indexed
+ for the x86_64 architecture. Indexing started in December 2021, packages
+ and releases not available in the repositories at that time have not
+ been indexed. I haven't found an archive for version 2.x releases
+ yet.</dd>
+ <dt>Arch Linux</dt><dd>
+ The core, extra and community repositories are fetched from a local
+ Arch mirror. Indexing started around begin June 2012. The i686
+ architecture was indexed until November 6th, 2016, packages after that
+ were fetched from from x86_64.</dd>
+ <dt>Debian</dt><dd>
+ Historical releases were fetched from <a
+ href="http://archive.debian.org/debian/">http://archive.debian.org/debian/</a>
+ and <a href="http://snapshot.debian.org/">http://snapshot.debian.org/</a>.
+ For buzz, rex and bo, we're missing a few man pages because some packages
+ were missing from the repository archives. Where available, all components
+ (main, contrib and non-free) from the $release and $release-updates
+ repositories are indexed.</dd>
+ <dt>CentOS</dt><dd>
+ Historical releases were fetched from <a
+ href="http://vault.centos.org/">vault.centos.org</a>, current releases
+ from a local mirror. Where applicable, the following repositories were
+ indexed: addons, centosplus, contrib, extras, os. The i386 architecture
+ was indexed for versions lower than 7.0, since 7.0 the packages from
+ x86_64 are indexed.
+ <dt>Fedora</dt><dd>
+ Historical releases were fetched from <a
+ href="http://archives.fedoraproject.org/pub/archive/fedora/linux/">archives.fedoraproject.org</a>,
+ current releases from a local repository. Fedora Core 1 till 6 are
+ (incorrectly) called 'Fedora' here. To compensate for that, Fedora 3 till
+ 6 also include the Extras repository. For Fedora 7 and later, the
+ 'Everything' and 'updates' repositories are indexed. The i386 arch was
+ indexed for Fedora 17 and older, the x86_64 arch starting with Fedora
+ 18.</dd>
+ <dt>FreeBSD</dt><dd>
+ Historical releases were fetched from <a
+ href="http://ftp-archive.freebsd.org/mirror/FreeBSD-Archive/">http://ftp-archive.freebsd.org/mirror/FreeBSD-Archive/</a>.
+ The base installation tarballs are included in the database as packages
+ prefixed with <i>core-</i>. The package repositories have also been
+ indexed, except for 2.0.5 - 2.2.7 and 3.0 - 3.3 because those were not
+ available on the ftp archive. Only the -RELEASE repositories have been
+ included, which is generally a snapshot of the ports directory around the
+ time of the release. The release dates indicated for many packages were
+ guessed from the file modification dates in the tarball, and may be
+ inaccurate. The i368 arch was indexed for FreeBSD 11.0 and older, the
+ amd64 arch starting with 11.1.</dd>
+ <dt>NetBSD</dt><dd>
+ Only the core installation sets have been indexed, <a
+ href="https://www.pkgsrc.org/">pkgsrc</a> is awesome but out of scope
+ for now. The i368 arch was indexed for 5.x and older, the amd64 arch
+ starting with 6.0. Releases before 1.3 only distributed preformatted man
+ pages and have therefore not been indexed. The original roff sources
+ could perhaps be extracted from the source tarballs, but that's a
+ project for another time.</dd>
+ <dt>Ubuntu</dt><dd>
+ Historical releases were fetched from <a
+ href="http://old-releases.ubuntu.com/ubuntu/">http://old-releases.ubuntu.com/ubuntu/</a>,
+ supported releases from a local mirror. All components (main, universe,
+ restricted and multiverse) from the $release, $release-updates and
+ $release-security repositories are indexed. Indexing started around mid
+ June 2012. All releases before 2017 were indexed from the i386
+ repositories, starting with 17.04 the amd64 repositories were used.</dd>
+ </dl>
+ <p>
+ Only packages for a single architecture (i386 or amd64) are scanned. To my
+ knowledge, packages that come with different manuals for different
+ architectures either don't exist or are extremely rare. It does happen that
+ some packages are not available for all architectures. Usually, though,
+ every package is at least available for the most popular architecture, so
+ hopefully we're not missing out on much. <br /><br />
+ The repositories are scanned for new packages on a daily basis.
+ </p>
+
+ <h2 id="database-download">Database download</h2>
+ <p>
+ This site is backed by a PostgreSQL database containing all the man pages.
+ Weekly dumps of the full database are available for download at
+ <a href="http://dl.manned.org/dumps/">http://dl.manned.org/dumps/</a>.
+ <br /><br />
+ Be warned that the download server may not be terribly fast or reliable,
+ so it is advisable to use a client that supports resumption of partial
+ downloads. See <a href="/wget">wget's -c</a> or
+ <a href="/curl">curl's -C</a>.
+ <br /><br />
+ The database schema is "documented" at <a
+ href="https://code.blicky.net/yorhel/manned/src/branch/master/sql/schema.sql">schema.sql</a>
+ in the git repo. Keep in mind that these dumps don't constitute a stable
+ API and, while this won't happen frequently, incompatible schema changes
+ or Postgres major version bumps will occassionally occur.
+ </p>
+
+ <h2 id="future-plans">Future plans</h2>
+ <p>
+ This site isn't nearly as awesome yet as it could be. Here's some ideas that
+ would be nice to have in the future:
+ <ul>
+ <li>Index a few more systems: Gentoo (now that it has official binary packages), OpenBSD and perhaps others.</li>
+ <li>Better browsing and discovery features.</li>
+ <li>Improved, more intelligent, search,</li>
+ <li><a href="/apropos.1">apropos(1)</a> emulation(?),</li>
+ <li>Diffs between various versions of a man page,</li>
+ <li>Anchor links within man pages, for easier linking to a section or paragraph,</li>
+ <li>Alternative formats (Text, PDF, more semantic HTML, etc),</li>
+ <li>A command-line client, like <a href="/man.1">man(1)</a> with manned.org as database backend.</li>
+ </ul>
+ </p>
+
+ <h2 id="copyright">Copyright</h2>
+ <p>
+ All manual pages are copyrighted by their respective authors. The manuals
+ have been fetched from publically available repositories of free and
+ (primarily) open source software. The distributors of said software have put
+ in efforts to only include software and documentation that allows free
+ distribution. Nonetheless, if a manual that does not allow to be
+ redistributed has been inadvertently included in our index, please let me
+ know and I will have it removed as soon as possible.
+ </p>
+ _
+ };
+};
- my($pkg, $ver) = pkg_frompath($self, $sys->{id}, $path); # Handles (2) and (3)
- return $self->resNotFound if !$pkg;
- my $verid = $ver && $self->dbPackageVersions($pkg->{id}, $ver)->[0]{id};
- return $self->resNotFound if $ver && !$verid;
+# Very simple (and fast) prefix match.
+sub search_man {
+ my($q, $limit) = @_;
+
+ my $sect = $q =~ s/^([0-9])\s+// || $q =~ s/\(([a-zA-Z0-9]+)\)$// ? $1 : '';
+ my $name = $q =~ s/^([a-zA-Z0-9,.:_-]+)// ? $1 : '';
+
+ return !$name ? [] : tuwf->dbAlli(
+ 'SELECT name, section FROM mans WHERE', sql_and(
+ sql('lower(name) LIKE', \(escape_like(lc $name).'%')),
+ $sect ? sql('section ILIKE', \(escape_like(lc $sect).'%')) : (),
+ ), 'ORDER BY name, section LIMIT', \$limit,
+ );
+}
- ($man) = $self->dbManPrefName($name, sysid => $sys->{id}, pkgid => $pkg->{id}, pkgver => $verid);
- }
- return $self->resNotFound if !$man;
- $self->resRedirect("/$man->{name}/".substr($man->{hash}, 0, 8), 'temp');
+TUWF::get '/browse/search' => sub {
+ my $q = tuwf->reqGet('q')||'';
+ my $man = search_man $q, 150;
+ return tuwf->resRedirect("/$man->[0]{name}.$man->[0]{section}", 'temp') if @$man == 1;
+
+ framework_ title => 'Search results for '.$q, mainclass => 'searchres', sub {
+ h1_ 'Search results for '.$q;
+ # Package search would also be useful.
+ p_ 'Note: This is just a simple case-insensitive prefix match on the man names. In the future we\'ll have more powerful search functionality. Hopefully.';
+ if(@$man) {
+ ul_ sub {
+ li_ sub {
+ a_ href => "/$_->{name}.$_->{section}", $_->{name};
+ small_ " $_->{section}";
+ } for @$man;
+ }
+ } else {
+ p_ 'No results :-(';
+ }
+ };
};
-sub _man_nav {
- my($self, $man, $toc) = @_;
+TUWF::get '/xml/search.xml' => sub {
+ my $q = tuwf->reqGet('q')||'';
+ my $man = search_man $q, 20;
+
+ tuwf->resHeader('Content-Type' => 'text/xml; charset=UTF-8');
+ xml;
+ tag 'results', sub {
+ tag 'item', id => "$_->{name}.$_->{section}", %$_, undef for @$man;
+ };
+};
- my @sect = $self->dbManSections($man->{name});
- my @lang = $self->dbManLanguages($man->{name}, $man->{section});
- return if !@sect && !@lang && !@$toc;
- # TODO: This is ugly, especially because clicking on a translation or
- # section, you can end up with a man page that is nowhere close to the man
- # page you're currently reading. Opening a version selector box might be a
- # better alternative.
+# Object to represent the various URLs to a man page.
+#
+# Parameters:
+# fmt => man|txt|raw
+# shorthash => 8-char hex
+# lang => language code
+# system => system shortname
+# category => package category
+# package => name of the package
+# version => package version
+# man => name of the man page
+# section => man page section
+#
+# URL format:
+# /$fmt[.$shorthash][.$lang][/$system[/$category/$package[/$version]]]/$man[.$section]
+#
+# Note that the URL format has some ambiguity:
+# - $category may contain a slash, so a database lookup is required to
+# disambiguate between URLs with [/$version] and those without.
+# - $man may contain a dot, so a database lookup is required to disambiguate
+# between URLs with [.$section] and those without
+#
+# $system may also refer to system shortnames without the version suffix (e.g.
+# 'ubuntu' rather than 'ubuntu-impish'). In that case the man page from the
+# latest release of that system is chosen.
+package ManUrl {
+ sub new { my($p,%o)=@_; bless \%o, $p }
+ sub set { my($o,@o)=@_; bless +{%$o,@o}, ref $o }
+ sub mansect { $_[0]{man}.(defined $_[0]{section} ? ".$_[0]{section}" : '') }
+ use overload '""' => sub {
+ my($o)=@_;
+ "/$o->{fmt}".(defined $o->{shorthash} ? ".$o->{shorthash}" : '').(defined $o->{lang} ? ".$o->{lang}" : '')
+ .(defined $o->{system} ? ("/$o->{system}"
+ .(defined $o->{category} ? ("/$o->{category}/$o->{package}"
+ .(defined $o->{version} ? "/$o->{version}" : '')) : '')) : '')
+ .'/'.$o->mansect
+ };
+};
- div id => 'nav';
- if(@sect > 1) {
- b 'Sections';
- p;
- for (@sect) {
- if($man->{section} eq $_) {
- i $_;
- } else {
- a href => "/$man->{name}.$_", $_;
- }
- txt ' ';
- }
- end;
- }
-
- if(@lang > 1) {
- b 'Languages';
- p;
- (my $cur = $man->{locale}||'') =~ s/\..*//;
- for (@lang) {
- if(($_||'') eq $cur) {
- i $_ || 'default';
- } else {
- a href => $_ ? "/lang/$_/$man->{name}.$man->{section}" : "/$man->{name}.$man->{section}", $_ || 'default';
+sub man_nav_ {
+ my($man, $url, $toc, $htmllang) = @_;
+
+ my @systems = tuwf->dbAlli('
+ SELECT DISTINCT p.system
+ FROM packages p
+ JOIN package_versions v ON v.package = p.id
+ JOIN files f ON f.pkgver = v.id
+ JOIN mans m ON m.id = f.man
+ WHERE m.name =', \$man->{name}, 'AND m.section =', \$man->{section}
+ )->@*;
+
+ my @sect = map $_->{section}, tuwf->dbAlli(
+ 'SELECT DISTINCT section FROM mans WHERE name =', \$man->{name}, 'ORDER BY section'
+ )->@*;
+
+ my @lang = map $_->{lang}, tuwf->dbAlli(
+ "SELECT DISTINCT substring(l.locale from '^[^.]+') AS lang
+ FROM files f
+ JOIN mans m ON m.id = f.man
+ JOIN locales l ON l.id = f.locale
+ WHERE m.name =", \$man->{name}, 'AND m.section =', \$man->{section}, "
+ ORDER BY substring(l.locale from '^[^.]+') NULLS FIRST"
+ )->@*;
+
+ nav_ sub {
+ form_ action => '/sysredir/'.$url->mansect(), method => 'get',
+ onsubmit => 'location.href="/man/"+system_select[system_select.selectedIndex].value+"/'.$url->mansect().'";return false',
+ sub {
+ my %names;
+ push $names{$_->{name}}->@*, $_ for map sysbyid->{$_->{system}}, sort { $b->{system} <=> $a->{system} } @systems;
+ select_ id => 'system_select', name => 'system', sub {
+ for (sort { ($names{$b}->@* == 1) <=> ($names{$a}->@* == 1) || $a cmp $b } keys %names) {
+ my $s = $names{$_};
+ if (@$s == 1) {
+ option_ value => $s->[0]{short}, selected => $s->[0]{id} == $man->{system}?'':undef, $s->[0]{full};
+ next;
+ }
+ optgroup_ label => $_, sub {
+ option_ value => $_->{short}, selected => $_->{id} == $man->{system}?'':undef, $_->{full} for @$s;
+ };
+ }
+ };
+ input_ type => 'submit', value => 'Go';
+ } if @systems > 1;
+
+ # TODO: This is ugly, especially because clicking on a translation or
+ # section, you can end up with a man page that is nowhere close to the
+ # man page you're currently reading. Sections or languages available
+ # for the currently selected system should be highlighted.
+ if(@sect > 1) {
+ b_ 'Sections';
+ p_ sub {
+ for (@sect) {
+ if($man->{section} eq $_) {
+ i_ $_;
+ } else {
+ a_ href => "/man/$man->{name}.$_", $_;
+ }
+ txt_ ' ';
+ }
+ }
}
- txt ' ';
- }
- end;
- }
-
- if(@$toc > 1) {
- b 'Table of Contents';
- ul;
- for (0..$#$toc) {
- li;
- a href => sprintf('#head%d', $_+1), lc $toc->[$_];
- end;
- }
- end;
- }
- end;
-}
+ if(@lang > 1) {
+ b_ 'Languages';
+ p_ sub {
+ (my $cur = $man->{locale}||'') =~ s/\..*//;
+ for (@lang) {
+ if(($_||'') eq $cur) {
+ i_ $_ || 'default';
+ } else {
+ a_ href => $_ ? "/man.$_/$man->{name}.$man->{section}" : "/man/$man->{name}.$man->{section}", $_ || 'default';
+ }
+ txt_ ' ';
+ }
+ }
+ }
-sub _normalizename {
- local $_ = shift;
- # Firefox seems to escape [ and ] in URLs. It doesn't really have to...
- s/%5b/[/ig;
- s/%5d/]/ig;
- # Man pages with spaces in the path, eww
- s/%20/ /g;
- $_;
+ if(@$toc > 1) {
+ b_ 'Table of Contents';
+ ul_ sub {
+ for (0..$#$toc) {
+ li_ sub {
+ a_ @$htmllang, href => sprintf('#head%d', $_+1), sub { lit_ lc $toc->[$_] };
+ }
+ }
+ }
+ }
+ }
}
# Replace .so's in man source with the contents (if available in the same
# package) or with a reference to the other man page.
sub soelim {
- my($self, $verid, $src) = @_;
-
- # tix comes with[1] a custom(?) macro package. But it looks okay even without
- # loading that.
- # [1] It actually doesn't, the tcllib package appears to have that file, but
- # doesn't '.so' it.
- $src =~ s/^\.so man.macros$//mg;
-
- # Other .so's should be handled by html()
- $src =~ s{^\.so (.+)$}{
- my $path = $1;
- my $name = (reverse split /\//, $path)[0];
- my($man) = $verid ? $self->dbManPrefName($name, pkgver => $verid) : ();
- if($man) {
- # Recursive soelim, but the second call gets $verid=0 so we don't keep checking the database
- soelim($self, 0, $self->dbManContent($man->{hash}))
- } else {
- ".in -10\n.sp\n\[\[\[MANNEDINCLUDE$path\]\]\]"
- }
- }emg;
- return $src;
-}
-
-
-sub man {
- my($self, $name, $hash) = @_;
-
- $name = _normalizename($name);
-
- # Unfortunately, even in the permalink format with the hash, we don't know
- # from which package we're supposed to get the man page. This info is
- # needed in order to do .so substitution, so we can substitute files from
- # the same package as the requested man page. Use the dbManPref logic here
- # to deterministically select a good package.
- my($man, undef) = $hash
- ? $self->dbManPref(name => $name, shorthash => $hash)
- : $self->dbManPrefName($name);
- return $self->resNotFound() if !$man;
-
- my $fmt = ManUtils::html(ManUtils::fmt_block soelim $self, $man->{verid}, $self->dbManContent($man->{hash}));
- my @toc;
- $fmt =~ s{\n<b>(.+?)<\/b>\n}{
- push @toc, $1;
- my $c = @toc;
- qq{\n<a href="#head$c" id="head$c">$1</a>\n}
- }eg;
-
- $self->setLastMod($man->{released});
- $self->htmlHeader(title => $name);
- _man_nav($self, $man, \@toc);
- div id => 'manbuttons';
- h1 $man->{name};
- ul 'data-hash' => $man->{hash}, 'data-name' => $man->{name}, 'data-section' => $man->{section}, 'data-locale' => $man->{locale}||'',
- 'data-hasversions' => $self->dbManHasVersions($man->{name}, $man->{section}, $man->{locale}, $man->{hash});
- li; a href => "/$man->{name}/".substr($man->{hash}, 0, 8).'/src', 'source'; end;
- li; a href => "/$man->{name}/".substr($man->{hash}, 0, 8), 'permalink'; end;
- end;
- end;
- div id => 'manres', class => 'hidden';
- end;
-
- div id => 'contents';
- pre; lit $fmt; end;
- end;
- $self->htmlFooter();
-}
-
-
-sub src {
- my($self, $name, $hash) = @_;
-
- $name = _normalizename($name);
-
- my $m = $self->dbManInfo(name => $name, shorthash => $hash);
- return $self->resNotFound if !@$m;
-
- $self->setLastMod($m->[0]{released});
- $self->resHeader('Content-Type', 'text/plain; charset=UTF-8');
- $self->resHeader('Content-Disposition', sprintf 'filename="%s.%s"', $m->[0]{name}, $m->[0]{section});
- my $c = $self->dbManContent($m->[0]{hash});
- lit $c;
-}
-
-
-sub xmlsearch {
- my $self = shift;
- my $q = $self->reqGet('q')||'';
- my $man = $self->dbSearch($q, 20);
-
- # The JS dropdown search expects this particular format.
- $self->resHeader('Content-Type' => 'text/xml; charset=UTF-8');
- xml;
- tag 'results';
- tag 'item', id => "$_->{name}.$_->{section}", %$_, undef for(@$man);
- end 'results';
+ my($verid, $src) = @_;
+
+ # tix comes with* a custom(?) macro package. But it looks okay even without loading that.
+ # (* It actually doesn't, the tcllib package appears to have that file, but doesn't '.so' it)
+ $src =~ s/^\.so man.macros$//mg;
+
+ # Other .so's should be handled by html()
+ $src =~ s{^\.so (.+)$}{
+ my $path = $1;
+ my $name = (reverse split /\//, $path)[0];
+ my($man) = $verid ? man_pref_name $name, sql 'v.id =', \$verid : ();
+ $man->{name}
+ # Recursive soelim, but the second call gets $verid=0 so we don't keep checking the database
+ ? soelim(0, tuwf->dbVali("SELECT content FROM contents WHERE id =", \$man->{content}))
+ : ".in -10\n.sp\n\[\[\[MANNEDINCLUDE$path\]\]\]"
+ }emg;
+ $src;
}
-sub jsontree {
- my $self = shift;
-
- my $f = $self->formValidate(
- { get => 'name', required => 0, maxlength => 256 },
- { get => 'section', required => 0, maxlength => 32 },
- { get => 'locale', required => 0, default => '', maxlength => 32 },
- { get => 'cur', required => 0, default => '', regex => qr/^[a-fA-F0-9]{40}$/ },
- { get => 'hash', required => 0, default => '', regex => qr/^[a-fA-F0-9]{40}$/ },
- );
- return $self->resNotFound() if $f->{_err} || (!$f->{hash} && !($f->{section} && $f->{name}));
-
- my $l = $self->dbManInfo(sort => 'syspkgname', $f->{hash}
- ? (hash => $f->{hash})
- : (name => $f->{name}, section => $f->{section}, locale => $f->{locale}));
-
- # Convert the list into a tree
- my $tree = [];
- my($sys, $sysver, $pkg, $pkgver);
- for my $m (@$l) {
- my $sysname = $self->{sysbyid}{$m->{system}}{name};
- if(!$sys || $sysname ne $sys->{name}) {
- $sys = { name => $sysname, childs => [] };
- $sysver = undef;
- push @$tree, $sys;
- }
+sub man_page {
+ my($man, $url) = @_;
+ tuwf->resLastMod($man->{released});
- my $sysversion = $self->{sysbyid}{$m->{system}}{release} || '';
- if(!$sysver || $sysversion ne $sysver->{name}) {
- $sysver = { name => $sysversion, childs => [] };
- $pkg = undef;
- push @{$sys->{childs}}, $sysver;
+ my $content = tuwf->dbRowi('SELECT encode(hash, \'hex\') AS hash, content FROM contents WHERE id =', \$man->{content});
+ if($url->{fmt} eq 'raw') {
+ tuwf->resHeader('Content-Type', 'text/plain; charset=UTF-8');
+ tuwf->resHeader('Content-Disposition', sprintf 'filename="%s.%s"', $man->{name}, $man->{section});
+ lit $content->{content};
+ return;
}
- if(!$pkg || $m->{package} ne $pkg->{name}) {
- $pkg = { name => $m->{package}, i => $m->{category}, table => [] };
- $pkgver = undef;
- push @{$sysver->{childs}}, $pkg;
+ my $fmt = ManUtils::html ManUtils::fmt_block soelim $man->{verid}, $content->{content};
+ if($url->{fmt} eq 'txt') {
+ # TODO: The 'txt' format is kind of broken right now as it includes our HTML formatting codes.
+ # This feature is a WIP and not advertised at the moment, anyway.
+ tuwf->resHeader('Content-Type', 'text/plain; charset=UTF-8');
+ tuwf->resHeader('Content-Disposition', sprintf 'filename="%s.%s.txt"', $man->{name}, $man->{section});
+ lit $fmt;
+ return;
}
- push @{$pkg->{table}}, [
- $pkgver && $pkgver eq $m->{version} ? {name=>''} :
- {name => $m->{version}, href => "/pkg/$self->{sysbyid}{$m->{system}}{short}/$m->{category}/$m->{package}/$m->{version}"},
- { name => "$m->{name}($m->{section})",
- $f->{hash} || lc($m->{hash}) eq lc($f->{cur}) ? ()
- : (href => sprintf('/%s/%s', $m->{name}, substr $m->{hash}, 0, 8))
- },
- { name => substr($m->{hash}, 0, 8),
- $f->{hash} || lc($m->{hash}) eq lc($f->{cur}) ? ()
- : (href => sprintf('/%s/%s', $m->{name}, substr $m->{hash}, 0, 8))
- },
- { name => $m->{filename} }
- ];
- $pkgver = $m->{version};
- }
-
- # Determine which elements to show/hide by default.
- # It might make more sense to do this in JS, but since I am utterly
- # incapable of writing maintainable JS I'm doing it here in order to keep the
- # JS stupid and simple.
- # TODO: Highlight systems/packages where the 'current' man page is?
- for my $sys (@$tree) {
- $sys->{expand} = 1 if $sys->{childs}[0]{name}; # Expand all systems that have named versions
- $sys->{expand} = 1 if $f->{hash}; # Expand everything on 'location'
-
- my $i = 0;
- for my $sysver (@{$sys->{childs}}) {
- $i++;
- $sysver->{expand} = 1 if !$sysver->{name}; # Expand unnamed versions (since you can't click them)
- $sysver->{expand} = 1 if $f->{hash}; # Expand everything on 'location'
- $sysver->{hide} = 1 if $i > 3 && @{$sys->{childs}} > 5; # Show only the first 3 versions
-
- for my $pkg (@{$sysver->{childs}}) {
- $pkg->{expand} = 1 if @{$sysver->{childs}} <= 3; # Expand everything if there's not too many things to expand
- $pkg->{expand} = 1 if $f->{hash}; # Expand everything on 'location'
-
- # TODO: Show/Hide duplicate hashes?
- }
- }
- }
-
- # Why JSON? Because TUWF::XML is pretty slow with many nodes
- $self->resHeader('Content-Type' => 'application/json; charset=UTF-8');
- lit(JSON::XS->new->ascii->encode($tree));
+ # Prefix links to other man pages with the current system, to ensure we
+ # grab the most relevant man page.
+ # XXX: This is a hack, prefixing is better done directly in ManUtils.
+ my $sys = sysbyid->{$man->{system}}{short};
+ $fmt =~ s{<a href="/}{<a href="/man/$sys/}g;
+
+ my @toc;
+ $fmt =~ s{\n<b>([^<\n]+?)<\/b>\n}{
+ push @toc, $1;
+ my $c = @toc;
+ qq{\n<a href="#head$c" id="head$c">$1</a>\n}
+ }eg;
+
+ my $hasversions = tuwf->dbVali(
+ 'SELECT 1
+ FROM files f
+ JOIN mans m ON m.id = f.man
+ JOIN locales l ON l.id = f.locale
+ WHERE m.name =', \$man->{name}, 'AND m.section =', \$man->{section}, '
+ AND l.locale =', \$man->{locale}, '
+ AND f.shorthash <> ', \$man->{shorthash}, '
+ LIMIT 1'
+ );
+ my @htmllang = $man->{locale} =~ /^([a-z]{2,3})(?:_([A-Z]{2}))?(?:$|@|\.)/ ? (lang => $1.($2?"-$2":'')) : ();
+
+ framework_ title => $man->{name}, mainclass => 'manpage', sub {
+ man_nav_ $man, $url, \@toc, \@htmllang;
+ # TODO: Replace the 'versions' and 'locations' functionality with non-JS alternatives.
+ div_ id => 'manbuttons', sub {
+ h1_ $man->{name};
+ ul_ 'data-hash' => $content->{hash},
+ 'data-name' => $man->{name},
+ 'data-section' => $man->{section},
+ 'data-locale' => $man->{locale}||'',
+ 'data-hasversions' => $hasversions?1:0,
+ sub {
+ li_ sub { a_ href => $url->set(fmt => 'raw'), 'source' };
+ li_ sub { a_ href => $url->set(system => sysbyid->{$man->{system}}{short}, category => undef, shorthash => shorthash_to_hex $man->{shorthash}), 'permalink' };
+ }
+ };
+ div_ id => 'manres', class => 'hidden', '';
+ pre_ @htmllang, sub { lit_ $fmt };
+ };
}
+# /<name>[.section] - short and handy catch-all URL for man pages
+# /<name>/<shorthash> - old permalink format
+# This one has to go before the other mappings, to ensure that links work for
+# man pages called 'pkg' or 'man'.
+TUWF::get qr{/(?<name>[^/]+)(?:/(?<hash>[0-9a-f]{8}))?} => sub {
+ my $name = normalize_name tuwf->capture('name');
+ my $shorthash = tuwf->capture('hash');
-package TUWF::Object;
-
-use TUWF ':html', 'html_escape';
-use Time::Local 'timegm';
+ my($man, $sect) = man_pref_name $name, $shorthash ? sql 'f.shorthash =', \shorthash_to_int $shorthash : 'true';
+ return tuwf->resNotFound() if !$man->{name};
-sub escape_like {
- (my $v = shift) =~ s/([_%])/\\$1/g;
- $v;
-}
+ man_page $man, ManUrl->new(
+ fmt => 'man',
+ man => length $sect ? $man->{name} : $name,
+ section => length $sect ? $sect : undef,
+ );
+};
-sub htmlHeader {
- my $self = shift;
- my %o = @_;
+# /<name>/<shorthash>/src - old URL format to get the raw man page
+TUWF::get qr{/([^/]+)/([0-9a-f]{8})/src} => sub {
+ my $name = normalize_name tuwf->capture(1);
+ my $shorthash = tuwf->capture(2);
- html;
- head;
- Link rel => 'stylesheet', type => 'text/css', href => '/man.css?4';
- title $o{title}.' - manned.org';
- end 'head';
- body;
+ my($man) = man_pref_name $name, sql 'f.shorthash =', \shorthash_to_int $shorthash;
+ return tuwf->resNotFound if !$man->{name};
+ man_page $man, ManUrl->new(fmt => 'raw', man => $name);
+};
- div id => 'header';
- a href => '/', 'manned.org';
- form action => '/browse/search', method => 'get';
- input type => 'text', name => 'q', id => 'q', tabindex => 1;
- input type => 'submit', value => ' ';
- end;
- end;
- div id => 'body';
-}
+TUWF::get qr{/(?<fmt>man|txt|raw)(?:\.(?<shorthash>[a-fA-F0-9]{8}))?(?:\.(?<lang>[^/]+))?/(?<path>.+)} => sub {
+ my($fmt, $shorthash, $lang, $path) = tuwf->captures(qw|fmt shorthash lang path|);
+ my @where;
+ my $name = normalize_name($path =~ s{/?([^/]+)$}{} && $1);
+ my $system = $path =~ s{^([^/]+)/?}{} && $1;
-sub htmlFooter {
- my($self, %o) = @_;
-
- br style => 'clear: both';
- end;
- div id => 'footer';
- lit 'All manual pages are copyrighted by their respective authors.
- | <a href="/info/about">About manned.org</a>
- | <a href="mailto:contact@manned.org">Contact</a>
- | <a href="https://code.blicky.net/yorhel/manned">Source</a>';
- end;
- script type => 'text/javascript', src => '/man.js', '';
- end;
- end 'html';
-
- # write the SQL queries as a HTML comment when debugging is enabled
- # (stolen from VNDB code)
- if($self->debug) {
- lit "\n<!--\n SQL Queries:\n";
- for (@{$self->{_TUWF}{DB}{queries}}) {
- my $q = !ref $_->[0] ? $_->[0] :
- $_->[0][0].(exists $_->[0][1] ? ' | "'.join('", "', map defined()?$_:'NULL', @{$_->[0]}[1..$#{$_->[0]}]).'"' : '');
- $q =~ s/^\s//g;
- lit sprintf " [%6.2fms] %s\n", $_->[1]*1000, $q;
+ # $sys can be either a full system 'short' name, or a prefix (e.g. 'debian' meaning 'any debian-* version')
+ if($system) {
+ my $sysid = sysbyshort->{$system};
+ $sysid = $sysid ? [$sysid->{id}] : [ map sysbyshort->{$_}{id}, grep /^\Q$system\E-/, keys sysbyshort->%* ];
+ return tuwf->resNotFound if !@$sysid;
+ push @where, sql 'system IN', $sysid;
}
- lit "-->\n";
- }
-}
-
-
-# Set the last modification time from a string in yyyy-mm-dd format.
-sub setLastMod {
- my($s, $d) = @_;
- return if $d !~ /^(\d{4})-(\d{2})-(\d{2})/;
- my @t = gmtime timegm 0,0,0,$3,$2-1,$1;
- $s->resHeader('Last-Modified', sprintf '%s, %02d %s %04d %02d:%02d:%02d GMT',
- (qw|Sun Mon Tue Wed Thu Fri Sat|)[$t[6]], $t[3],
- (qw|Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec|)[$t[4]],
- $t[5]+1900, $t[2], $t[1], $t[0]);
-}
-
-
-sub dbManContent {
- my($s, $hash) = @_;
- return $s->dbRow(q{SELECT content FROM contents WHERE hash = decode(?, 'hex')}, $hash)->{content};
-}
-
-
-# Options: name, section, shorthash, package, results, sort, countonly
-sub dbManInfo {
- my $s = shift;
- my %o = (
- sort => '',
- page => 1,
- results => 10_000,
- @_
- );
-
- my %where = (
- $o{name} ? ('m.name = ?' => $o{name}) : (),
- $o{package} ? ('m.package = ?' => $o{package}) : (),
- defined($o{section}) ? ('m.section = ?' => $o{section}) : (),
- $o{locale} ? ('m.locale = ?' => $o{locale}) : (),
- defined($o{locale}) && !$o{locale} ? ('m.locale IS NULL' => 1) : (),
- $o{shorthash} ? (q{substring(m.hash from 1 for 4) = decode(?, 'hex')} => $o{shorthash}) : (),
- $o{hash} ? (q{m.hash = decode(?, 'hex')} => $o{hash}) : (),
- );
-
- my $order =
- $o{sort} eq 'syspkgname' ? 'ORDER BY s.name, s.relorder DESC, p.name, v.released DESC, m.name, m.locale NULLS FIRST, m.filename' : '';
-
- my $select = $o{countonly} ? 'COUNT(*) as count'
- : "p.system, p.category, p.name AS package, v.version, v.released, v.id AS verid, m.name, m.section, m.filename, m.locale, encode(m.hash, 'hex') AS hash";
-
- my($r, $np) = $s->dbPage(\%o, q{
- SELECT !s
- FROM man m
- JOIN package_versions v ON v.id = m.package
- JOIN packages p ON p.id = v.package
- JOIN systems s ON s.id = p.system
- !W
- !s
- }, $select, \%where, $order);
- wantarray ? ($r, $np) : $r;
-}
-
-# Very simple (and fast) prefix match.
-sub dbSearch {
- my($s, $q, $limit) = @_;
-
- my $sect = $q =~ s/^([0-9])\s+// || $q =~ s/\(([a-zA-Z0-9]+)\)$// ? $1 : '';
- my $name = $q =~ s/^([a-zA-Z0-9,.:_-]+)// ? $1 : '';
-
- return !$name ? [] : $s->dbAll(
- 'SELECT name, section FROM man_index !W ORDER BY name, section LIMIT ?',
- {
- 'lower(name) LIKE ?' => escape_like(lc $name).'%',
- $sect ? ('section ILIKE ?' => escape_like(lc $sect).'%') : (),
- },
- $limit
- );
-}
-
-
-# Get the preferred man page for the given filters. Returns a row with the same fields as dbManInfo().
-sub dbManPref {
- my($s, %o) = @_;
- my %where = (
- length $o{name} ? ('m.name = ?' => $o{name}) : (),
- $o{shorthash} ? (q{substring(m.hash from 1 for 4) = decode(?, 'hex')} => $o{shorthash}) : (),
- length $o{section} ? ('m.section LIKE ?' => escape_like($o{section}).'%') : (),
- $o{sysid} ? ('p.system = ?' => $o{sysid}) : (),
- $o{package} ? ('p.id = ?' => $o{package}) : (),
- $o{pkgver} ? ('v.id = ?' => $o{pkgver}) : (),
- $o{language} ? (q{substring(locale from '^[^.]+') = ?} => $o{language}) : (),
- );
-
- # Criteria to determine a "preferred" man page:
- # 1. english: English versions of a man page have preference over other locales
- # 2. pkgver: Newer versions of the same package have preference over older versions
- # 3. stdloc: Prefer man pages in standard locations
- # 4. secmatch: Prefer an exact section match
- # 5. arch: Prefer Arch over other systems (because it tends to be the most up-to-date, and closest to upstreams)
- # 6. sysrel: Prefer a later system release over an older release
- # 7. secorder: Lower sections before higher sections (because man does it this way, for some reason)
- # 8. pkgdate: Prefer more recent packages (cross-distro)
- # 9. Fall back on hash comparison, to ensure the result is stable
-
- $s->dbAll(q{
- WITH unfiltered AS (
- SELECT s AS sys, p AS pkg, v AS ver, m AS man
- FROM man m
- JOIN package_versions v ON v.id = m.package
- JOIN packages p ON p.id = v.package
- JOIN systems s ON s.id = p.system
- !W
- ), f_english AS(
- SELECT * FROM unfiltered WHERE NOT EXISTS(SELECT 1 FROM unfiltered WHERE is_english_locale((man).locale)) OR is_english_locale((man).locale)
- ), f_pkgver AS(
- SELECT * FROM f_english a WHERE NOT EXISTS(SELECT 1 FROM f_english b WHERE (a.ver).package = (b.ver).package AND (a.ver).released < (b.ver).released)
- ), f_stdloc AS(
- SELECT * FROM f_pkgver WHERE NOT EXISTS(SELECT 1 FROM f_pkgver WHERE is_standard_man_location((man).filename)) OR is_standard_man_location((man).filename)
- ), f_secmatch AS(
- SELECT * FROM f_stdloc WHERE NOT EXISTS(SELECT 1 FROM f_stdloc WHERE (man).section = ?) OR (man).section = ?
- ), f_arch AS(
- SELECT * FROM f_secmatch WHERE NOT EXISTS(SELECT 1 FROM f_secmatch WHERE (sys).id = 1) OR (sys).id = 1
- ), f_sysrel AS(
- SELECT * FROM f_arch a WHERE NOT EXISTS(SELECT 1 FROM f_arch b WHERE (a.sys).name = (b.sys).name AND (a.sys).relorder < (b.sys).relorder)
- ), f_secorder AS(
- SELECT * FROM f_sysrel a WHERE NOT EXISTS(SELECT 1 FROM f_sysrel b WHERE (a.man).section > (b.man).section)
- ), f_pkgdate AS(
- SELECT * FROM f_secorder a WHERE NOT EXISTS(SELECT 1 FROM f_secorder b WHERE (a.ver).released < (b.ver).released)
- )
- SELECT (pkg).system, (pkg).category, (pkg).name AS package, (ver).version, (ver).released, (ver).id AS verid,
- (man).name, (man).section, (man).filename, (man).locale, encode((man).hash, 'hex') AS hash
- FROM f_pkgdate ORDER BY (man).hash LIMIT 1
- }, \%where, $o{section}||'', $o{section}||'')->[0];
-}
-
-
-# Given the name of a man page with optional section, find out the actual name
-# and section prefix of the man page and the preferred version.
-sub dbManPrefName {
- my($s, $name, %o) = @_;
-
- my $man = $s->dbManPref(%o, name => $name);
- return ($man, '') if $man;
-
- return (undef, '') if $name !~ s/\.([^.]+)$//;
- my $section = $1;
- $man = $s->dbManPref(%o, name => $name, section => $section);
- return ($man, $section) if $man;
- return (undef, '');
-}
-
-
-# Returns 1 of there are alternative versions of the given man page.
-sub dbManHasVersions {
- my($s, $name, $section, $locale, $hash) = @_;
- return $s->dbRow(
- q{SELECT 1 AS ok FROM man WHERE name = ? AND section = ? AND locale IS NOT DISTINCT FROM ? AND hash <> decode(?, 'hex') LIMIT 1},
- $name, $section, $locale, $hash
- )->{ok}||0;
-}
+ # $path is now either:
+ # 1. $category/$package
+ # 2. $cagegory/$package/$version
+ my($pkg, $ver) = length $path ? pkg_frompath sql_and(@where), $path : (undef,undef);
+ return tuwf->resNotFound if length $path && !$pkg;
+ push @where, sql 'p.id =', \$pkg->{id} if $pkg;
+ push @where, sql 'v.version =', \$ver if length $ver;
+
+ push @where, sql 'f.shorthash =', \shorthash_to_int $shorthash if $shorthash;
+ push @where, sql 'l.locale ilike', \(escape_like($lang).'%') if $lang;
+
+ my($man, $section) = man_pref_name $name, sql_and @where;
+ return tuwf->resNotFound if !$man;
+
+ my $url = ManUrl->new(
+ fmt => $fmt,
+ shorthash => $shorthash,
+ lang => $lang,
+ system => length $system ? $system : undef,
+ category => $pkg ? $pkg->{category} : undef,
+ package => $pkg ? $pkg->{name} : undef,
+ version => length $ver ? $ver : undef,
+ man => length $section ? $man->{name} : $name,
+ section => length $section ? $section : undef,
+ );
+ man_page $man, $url;
+};
-# Returns all available languages for a man page
-sub dbManLanguages {
- my($s, $name, $section) = @_;
- return map $_->{lang}, @{$s->dbAll(q{SELECT DISTINCT substring(locale from '^[^.]+') AS lang
- FROM man WHERE name = ? AND section = ?
- ORDER BY substring(locale from '^[^.]+') NULLS FIRST
- }, $name, $section)};
-}
+TUWF::get qr{/pkg/([^/]+)} => sub {
+ my $short = tuwf->capture(1);
+
+ my $sys = sysbyshort->{$short};
+ return tuwf->resNotFound if !$sys;
+
+ my $f = tuwf->validate(get =>
+ c => { onerror => 'all', enum => [ '0', 'all', 'a'..'z' ] },
+ p => { onerror => 1, uint => 1, range => [1,200] },
+ )->data;
+
+ my $where = sql 'NOT dead AND system =', \$sys->{id}, $f->{c} ne 'all' ? ('AND match_firstchar(name,', \$f->{c}, ')') : ();
+ my $count = tuwf->dbVali('SELECT count(*) FROM', $packages_with_man, 'p WHERE', $where);
+ my $pkg = tuwf->dbPagei({ results => 200, page => $f->{p} },
+ 'SELECT id, system, name, category, dead FROM', $packages_with_man, 'p WHERE', $where, 'ORDER BY name, category'
+ );
+
+ framework_ title => $sys->{full}, mainclass => 'pkglist', sub {
+ div_ sub {
+ div_ sub {
+ h1_ $sys->{full};
+ };
+ nav_ class => 'charselect', sub {
+ for('all', 0, 'a'..'z') {
+ a_ href => "/pkg/$short?c=$_", $_?uc$_:'#' if $_ ne $f->{c};
+ b_ $_?uc$_:'#' if $_ eq $f->{c};
+ }
+ };
+ };
+ small_ '(Packages without man pages are not listed)';
+
+ paginate_ "/pkg/$short?c=$f->{c};p=", $count, 200, $f->{p};
+ ul_ sub {
+ li_ sub {
+ a_ href => "/pkg/$short/$_->{category}/$_->{name}", $_->{name};
+ small_ ' '.$_->{category};
+ } for @$pkg;
+ };
+ paginate_ "/pkg/$short?c=$f->{c};p=", $count, 200, $f->{p};
+ };
+};
-# Returns all available languages for a man page
-sub dbManSections {
- my($s, $name) = @_;
- return map $_->{section}, @{$s->dbAll(q{SELECT DISTINCT section FROM man WHERE name = ? ORDER BY section}, $name)};
-}
-
+# Package info: /pkg/$system/$category/$name (/$version); $category may contain a slash, too.
+TUWF::get qr{/pkg/([^/]+)/(.+)} => sub {
+ my ($short, $path) = tuwf->captures(1,2);
+
+ my $sys = sysbyshort->{$short};
+ return tuwf->resNotFound if !$sys;
+
+ my($pkg, $ver) = pkg_frompath(sql('system =', \$sys->{id}), $path);
+ return tuwf->resNotFound if !$pkg;
+
+ my $vers = tuwf->dbAlli('
+ SELECT id, version, released
+ FROM package_versions v
+ WHERE package =', \$pkg->{id}, '
+ AND EXISTS(SELECT 1 FROM files f WHERE f.pkgver = v.id)
+ ORDER BY released DESC'
+ );
+ my $sel = $ver ? (grep $_->{version} eq $ver, @$vers)[0] : $vers->[0];
+ return tuwf->resNotFound if !$sel;
+
+ my $p = tuwf->validate(get => p => { onerror => 1, uint => 1, range => [1,100] })->data;
+
+ my $count = tuwf->dbVali('SELECT count(*) FROM files WHERE pkgver =', \$sel->{id});
+ my $mans = tuwf->dbPagei({ results => 200, page => $p }, '
+ WITH lst AS (
+ SELECT f.man, m.name, m.section, f.shorthash, f.filename, l.locale
+ FROM files f
+ JOIN locales l ON l.id = f.locale
+ JOIN mans m ON m.id = f.man
+ WHERE f.pkgver =', \$sel->{id}, '
+ ), needlang AS (
+ SELECT man FROM lst GROUP BY man HAVING count(*) > 1
+ ), needhash AS (
+ SELECT man, locale FROM lst GROUP BY man, locale HAVING count(*) > 1
+ ) SELECT name, section, shorthash, filename, locale
+ , EXISTS(SELECT 1 FROM needlang WHERE man = l.man) AS needlang
+ , EXISTS(SELECT 1 FROM needhash WHERE man = l.man AND locale = l.locale) AS needhash
+ FROM lst l
+ ORDER BY name, section, locale, filename
+ ');
+
+ # Latest version of this package determines last modification date of the page.
+ tuwf->resLastMod($vers->[0]{released});
+
+ my $subtitle = " / $pkg->{category} / $pkg->{name}";
+ my $pkgpath = "$sys->{short}/$pkg->{category}/$pkg->{name}";
+ framework_ title => "$sys->{full}$subtitle $sel->{version}", mainclass => 'pkgpage', sub {
+ h1_ sub {
+ a_ href => "/pkg/$sys->{short}", $sys->{full};
+ txt_ $subtitle;
+ };
+
+ div_ sub {
+ section_ sub {
+ h2_ 'Versions';
+ ul_ sub {
+ li_ sub {
+ a_ href => "/pkg/$pkgpath/$_->{version}", $_->{version} if $_ != $sel;
+ b_ " $_->{version}" if $_ == $sel;
+ small_ " $_->{released}";
+ } for(@$vers);
+ }
+ };
+
+ section_ sub {
+ h2_ "Manuals for version $sel->{version}";
+ paginate_ "/pkg/$pkgpath/$sel->{version}?p=", $count, 200, $p;
+ ul_ sub {
+ li_ sub {
+ # Only add the hash or locale to the URL if it's necessary to select the proper man page.
+ my $ext = $_->{needhash} ? '.'.shorthash_to_hex $_->{shorthash} : $_->{needlang} && length $_->{locale} ? ".$_->{locale}" : '';
+ a_ href => "/man$ext/$pkgpath/$sel->{version}/$_->{name}.$_->{section}", "$_->{name}($_->{section})";
+ b_ " $_->{locale}" if $_->{locale};
+ small_ " $_->{filename}";
+ } for(@$mans);
+ };
+ paginate_ "/pkg/$pkgpath/$sel->{version}?p=", $count, 200, $p;
+ };
+ };
+ }
+};
-sub dbSystemGet {
- return shift->dbAll('SELECT id, name, release, short, relorder FROM systems ORDER BY name, relorder');
-}
+# /browse/<pkg> has been moved to /pkg/ with the package category added to the path
+TUWF::get qr{/browse/([^/]+)} => sub { tuwf->resRedirect('/pkg/'.tuwf->capture(1), 'perm') };
+TUWF::get qr{/browse/([^/]+)/([^/]+)(?:/([^/]+))?} => sub {
+ my($sys, $name, $ver) = tuwf->captures(1,2,3);
+ $sys = sysbyshort->{$sys};
+ return tuwf->resNotFound if !$sys;
+ my $pkgs = tuwf->dbRowi('SELECT category FROM packages WHERE system =', \$sys->{id}, 'AND name =', \$name, 'LIMIT 1');
+ return tuwf->resNotFound if !defined $pkgs->{category};
+ tuwf->resRedirect("/pkg/$sys->{short}/$pkgs->{category}/$name".($ver ? "/$ver" :''), 'perm');
+};
-# Options: sysid char hasman page results countonly
-sub dbPackageGet {
- my $s = shift;
- my %o = (results => 10, page => 1, @_);
-
- my @where = (
- $o{sysid} ? ('system = ?' => $o{sysid} ) : (),
- $o{category} ? ('category = ?' => $o{category}) : (),
- $o{name} ? ('name = ?' => $o{name} ) : (),
- # This seems slow, perhaps cache?
- defined($o{hasman}) ? ('!s EXISTS(SELECT 1 FROM package_versions pv WHERE pv.package = p.id AND EXISTS(SELECT 1 FROM man m WHERE m.package = pv.id))' => $o{hasman}?'':'NOT') : (),
- $o{char} ? ( 'LOWER(SUBSTR(name, 1, 1)) = ?' => $o{char} ) : (),
- defined($o{char}) && !$o{char} ? ( '(ASCII(name) < 97 OR ASCII(name) > 122) AND (ASCII(name) < 65 OR ASCII(name) > 90)' => 1 ) : (),
- );
-
- my $select = $o{countonly} ? 'COUNT(*) as count' : 'id, system, name, category';
- my $order = $o{countonly} ? '' : 'ORDER BY name';
-
- my($r, $np) = $s->dbPage(\%o,
- 'SELECT !s FROM packages p !W !s',
- $select, \@where, $order
- );
- wantarray ? ($r, $np) : $r;
-}
+# Redirect for the system selection box, for visitors who have disabled JS.
+TUWF::get qr{/sysredir/([^/]+)} => sub { tuwf->resRedirect('/man/'.(tuwf->reqGet('system')//'arch').'/'.tuwf->capture(1), 'temp') };
+
+# Redirect for a specific language for a man page. I have no idea if anyone
+# still uses this URL format, but it was supported at some point, so let's keep
+# it around.
+TUWF::get qr{/lang/([^/]+)/([^/]+)} => sub { tuwf->resRedirect('/man.'.tuwf->capture(1).'/'.tuwf->capture(2), 'temp') };
+
+
+TUWF::get '/json/tree.json' => sub {
+ my $f = tuwf->validate(get =>
+ name => { default => '', maxlength => 256 },
+ section => { default => '', maxlength => 32 },
+ locale => { default => sub{$_[0]}, maxlength => 32 },
+ cur => { default => '', regex => qr/^[a-fA-F0-9]{40}$/ },
+ hash => { default => '', regex => qr/^[a-fA-F0-9]{40}$/ },
+ )->data;
+ return tuwf->resNotFound() if !$f->{hash} && !($f->{section} && $f->{name});
+
+ my $l = tuwf->dbAlli("
+ SELECT p.system, p.category, p.name AS package, v.version, v.released, v.id AS verid, m.name, m.section, f.filename, f.shorthash, l.locale
+ FROM files f
+ JOIN locales l ON l.id = f.locale
+ JOIN mans m ON m.id = f.man
+ JOIN package_versions v ON v.id = f.pkgver
+ JOIN packages p ON p.id = v.package
+ JOIN systems s ON s.id = p.system
+ WHERE", sql_and(
+ length $f->{hash} ? sql 'f.content = (SELECT id FROM contents WHERE hash = decode(', \$f->{hash}, ", 'hex'))" : (),
+ length $f->{name} ? sql 'm.name =', \$f->{name} : (),
+ length $f->{section} ? sql 'm.section =', \$f->{section} : (),
+ defined $f->{locale} ? sql 'l.locale =', \$f->{locale} : (),
+ ), '
+ ORDER BY s.name, s.id DESC, p.name, v.released DESC, m.name, l.locale, f.filename
+ ');
+
+ # Convert the list into a tree
+ my $cur = $f->{cur} ? shorthash_to_int substr $f->{cur}, 0, 8 : 0;
+ my $tree = [];
+ my($sys, $sysver, $pkg, $pkgver);
+ for my $m (@$l) {
+ my $sysname = sysbyid->{$m->{system}}{name};
+ if(!$sys || $sysname ne $sys->{name}) {
+ $sys = { name => $sysname, childs => [] };
+ $sysver = undef;
+ push @$tree, $sys;
+ }
+ my $sysversion = sysbyid->{$m->{system}}{release} || '';
+ if(!$sysver || $sysversion ne $sysver->{name}) {
+ $sysver = { name => $sysversion, childs => [] };
+ $pkg = undef;
+ push @{$sys->{childs}}, $sysver;
+ }
-sub dbPackageVersions {
- my($s, $id, $version) = @_;
+ if(!$pkg || $m->{package} ne $pkg->{name}) {
+ $pkg = { name => $m->{package}, i => $m->{category}, table => [] };
+ $pkgver = undef;
+ push @{$sysver->{childs}}, $pkg;
+ }
- my %where = (
- 'package = ?' => $id,
- $version ? ('version = ?' => $version) : (),
- 'EXISTS(SELECT 1 FROM man m WHERE m.package = v.id)' => 1,
- );
+ push @{$pkg->{table}}, [
+ $pkgver && $pkgver eq $m->{version} ? {name=>''} :
+ {name => $m->{version}, href => "/pkg/".sysbyid->{$m->{system}}{short}."/$m->{category}/$m->{package}/$m->{version}"},
+ { name => "$m->{name}($m->{section})",
+ $f->{hash} || $cur == $m->{shorthash} ? ()
+ : (href => sprintf('/%s/%s', $m->{name}, shorthash_to_hex $m->{shorthash}))
+ },
+ { name => shorthash_to_hex($m->{shorthash}),
+ $f->{hash} || $cur == $m->{shorthash} ? ()
+ : (href => sprintf('/%s/%s', $m->{name}, shorthash_to_hex $m->{shorthash}))
+ },
+ { name => $m->{filename} }
+ ];
+ $pkgver = $m->{version};
+ }
- return $s->dbAll(q{
- SELECT id, version, released
- FROM package_versions v !W
- ORDER BY released DESC},
- \%where)
-}
+ # Determine which elements to show/hide by default.
+ # It might make more sense to do this in JS, but since I am utterly
+ # incapable of writing maintainable JS I'm doing it here in order to keep the
+ # JS stupid and simple.
+ # TODO: Highlight systems/packages where the 'current' man page is?
+ for my $sys (@$tree) {
+ $sys->{expand} = 1 if $sys->{childs}[0]{name}; # Expand all systems that have named versions
+ $sys->{expand} = 1 if $f->{hash}; # Expand everything on 'location'
+
+ my $i = 0;
+ for my $sysver (@{$sys->{childs}}) {
+ $i++;
+ $sysver->{expand} = 1 if !$sysver->{name}; # Expand unnamed versions (since you can't click them)
+ $sysver->{expand} = 1 if $f->{hash}; # Expand everything on 'location'
+ $sysver->{hide} = 1 if $i > 3 && @{$sys->{childs}} > 5; # Show only the first 3 versions
+
+ for my $pkg (@{$sysver->{childs}}) {
+ $pkg->{expand} = 1 if @{$sysver->{childs}} <= 3; # Expand everything if there's not too many things to expand
+ $pkg->{expand} = 1 if $f->{hash}; # Expand everything on 'location'
+
+ # TODO: Show/Hide duplicate hashes?
+ }
+ }
+ }
+ tuwf->resJSON($tree);
+};
-sub dbStats {
- return $_[0]->dbRow('SELECT * FROM stats_cache');
-}
+TUWF::run();
diff --git a/www/man.css b/www/man.css
index 3e86d9f..a1dbe15 100644
--- a/www/man.css
+++ b/www/man.css
@@ -1,84 +1,54 @@
-/* TODO: column-width is better done in Perl? (More like a column-count, then) */
-
-* { margin: 0; padding: 0; font-family: "Trebuchet MS", sans-serif; }
-html { background: #333; padding: 0 10px; }
-body { margin: 10px auto 50px auto; max-width: 1100px; border-collapse: separate; padding-bottom: 10px; border-radius: 10px; box-shadow: 0 10px 10px #def; }
-h1 { font-size: 24px; font-weight: normal; color: #abc; }
-h2 { font-size: 21px; margin-top: 40px; color: #468; font-weight: normal; clear: left }
-h2 + i { font-size: 12px; }
-h3 { font-size: 16px; margin-top: 20px; color: #468; font-weight: normal }
-a { color: #048; }
+* { margin: 0; padding: 0; font-size: inherit; font-family: "Trebuchet MS", sans-serif; }
+html { background: #fff; padding: 0 10px; color: #000 }
+body { margin: 10px auto 50px auto; max-width: 1100px; border-collapse: separate; padding-bottom: 10px }
+h1 { font-size: 24px; font-weight: normal }
+h2 { font-size: 21px; margin-top: 35px; margin-bottom: 7px; font-weight: normal; border-bottom: 1px solid #ccc }
+h3 { font-size: 18px; margin-top: 20px; margin-bottom: 5px; font-weight: normal }
+a { color: #048; text-decoration: none }
a:hover { text-decoration: underline; color: #48B;}
-code { font-family: "Lucida Console", Monospace; font-size: 12px; background-color: #f0f8ff }
+p { margin-bottom: 15px }
+dl { margin-bottom: 15px }
+dt { margin: 0 0 5px 0 }
+dd { margin: 0 0 10px 10px; }
+ul { margin: 0 0 15px 20px }
+input { font-size: 0.9em; padding: 1px 2px }
+code { font-family: "Lucida Console", Monospace; font-size: 12px; background-color: #f0f8ff; padding: 1px }
+small { color: #aaa }
.hidden { display: none!important; }
-#header { padding: 4px 20px; border-bottom: 1px solid #888; font: 24px "Arial"; background: url('images/gradients.png') repeat-x; border-radius: 8px 8px 0 0; }
-#header a { color: #f8f8f8; text-decoration: none; font-weight: bold; }
-#header a:hover { background: none; }
-#header form { float: right; }
-#header input[type=text] { color: #000; width: 260px; padding: 1px 2px 1px 15px; border-radius: 12px 0 0 12px; border: 1px solid #444;
- box-shadow: 1px 1px 3px #fff, -1px -1px 2px #234; background: url('images/gradients.png') 0 -105px repeat-x; height: 15px; }
-#header input[type=text]:hover, #header input[type=text]:focus { background: url('images/gradients.png') 0 -122px repeat-x; outline: none; }
-#header input[type=submit] { height: 23px; width: 62px; background-image: url('images/search.png'); border: 0; margin: 0 0 0 -5px; cursor: pointer }
-
-#body { padding: 10px 10px 20px 10px; background: #fff }
-
-#systems a,
-.charselect a,
-.paginate a { color: #048; font-family: "Verdana"; font-weight: normal; text-decoration: none; padding: 3px 5px; border-radius: 4px; }
-
-.charselect b,
-.paginate b { font-family: "Verdana"; padding: 3px }
-
-#systems a:hover,
-.charselect a:hover,
-.paginate a:hover { background: #cde; }
-
-p.txt { margin: 5px 0 0 10px; max-width: 700px }
-#external { list-style-type: none; margin-left: 10px }
-
-i.grayedout { color: #aaa; font-size: 13px; }
-
-#about { max-width: 700px }
-#about h2 { margin-bottom: 5px }
-#about dl { margin-bottom: 5px }
-#about dt { margin: 5px 0 0 10px }
-#about p { margin: 0 0 0 10px; }
-#about dd { margin: 0 0 0 20px; }
-#about ul { padding: 5px 0 5px 30px }
-
-#systems li { display: block; float: left; width: 300px; min-height: 80px; margin: 15px 10px; padding-left: 60px }
-#systems span { display: block; margin-left: -55px; float: left; width: 50px; height: 50px; background-repeat: no-repeat; }
-#systems b { font-size: 24px; display: block }
-
-#pkglist .charselect { float: right }
-#pkglist .paginate { display: block; margin: 10px; width: 100%; text-align: center }
-
-#packages { margin: 20px 0; -webkit-column-width: 300px; -moz-column-width: 300px; column-width: 300px }
-#packages li { display: block; }
-#packages i { color: #aaa; font-size: 13px; }
-#packages a { padding-right: 2px }
-
-#searchres { margin: 20px 0; -webkit-column-width: 300px; -moz-column-width: 300px; column-width: 300px }
-#searchres li { display: block; }
-#searchres i { color: #aaa; font-size: 13px; }
-#searchres a { padding-right: 2px }
-
-#pkgversions { margin-top: 10px }
-#pkgversions h2 { margin: 0 }
-#pkgversions { float: left; padding: 0 10px; }
-#pkgversions ul { margin: 10px 0; padding-right: 10px; border-right: 1px dashed #468 }
-#pkgversions li { display: block; }
-#pkgversions i { color: #aaa; font-size: 13px; }
-#pkgversions a { padding-right: 2px }
-
-#pkgmans { margin-top: 10px }
-#pkgmans h2 { margin: 0 }
-#pkgmans { float: left }
-#pkgmans .paginate { margin: 10px 0 }
-#pkgmans ul { margin: 10px 0 }
-#pkgmans li { display: block }
-#pkgmans i { color: #aaa; font-size: 13px; }
+header { border-bottom: 3px dotted #ccc; display: flex; justify-content: space-between; align-items: end; flex-wrap: wrap }
+header a { font: 24px "Arial", serif; font-weight: bold }
+header form { padding-bottom: 3px }
+header input[type=text] { width: 100px }
+
+footer { border-top: 3px dotted #ccc; color: #666; font-size: 12px; display: flex; justify-content: space-between; flex-wrap: wrap }
+
+main { padding: 10px 0 25px 0 }
+main.thin { max-width: 700px; margin: 0 auto }
+
+.systems > div { margin: 25px 0; display: flex; align-items: start }
+.systems > div > a { display: flex; align-items: center }
+.systems img { width: 50px; height: 50px; margin-right: 10px }
+.systems b { font-size: 24px; display: block }
+.systems > div > div > a { padding-right: 10px }
+
+.searchres ul { margin: 20px 0; list-style-type: none; column-width: 300px }
+.searchres a { padding-right: 2px }
+
+.charselect a, .paginate a { display: inline-block; padding: 3px 5px }
+.charselect b, .paginate b { display: inline-block; padding: 3px 5px }
+
+.pkglist > div { display: flex; align-items: start; justify-content: space-between; flex-wrap: wrap }
+.pkglist .paginate { margin: 10px 0; text-align: center }
+.pkglist ul { margin: 20px 0; list-style-type: none; column-width: 300px }
+.pkglist ul a { padding-right: 2px }
+
+.pkgpage > div { display: flex; flex-wrap: wrap; margin-top: 15px }
+.pkgpage h2 { border-bottom: 0; margin: 0 0 10px 0 }
+.pkgpage ul { margin: 0; list-style-type: none }
+.pkgpage section:first-child { border-right: 1px dashed #468; padding: 0 10px }
+.pkgpage section:last-child { padding: 0 10px }
+
#manbuttons h1 { display: inline; margin: 0 20px 0 0; vertical-align: middle }
#manbuttons ul { list-style-type: none; display: inline-block }
@@ -91,7 +61,7 @@ i.grayedout { color: #aaa; font-size: 13px; }
#manres { margin: 0 0 10px 0; width: 70%; padding: 10px; box-sizing: border-box; background: #f0f8ff; border-radius: 10px; border-left: 1px dashed #333; border-right: 1px dashed #333 }
#manres i { color: #aaa; font-size: 13px; margin-left: 7px }
-#manres ul { list-style-type: none }
+#manres ul { list-style-type: none; margin-bottom: 0 }
#manres ul a { outline: none; text-decoration: none }
#manres ul .oldver a { color: #aaa; font-size: 13px }
#manres div > ul { margin-top: 5px } /* System names */
@@ -106,21 +76,21 @@ i.grayedout { color: #aaa; font-size: 13px; }
#manres table { margin: 2px 10px; }
#manres table tr td:nth-child(1) { min-width: 80px }
-#nav { background: #f0f8ff; color: #036; float: right; padding: 8px; width: 250px; margin-bottom: 10px; border-radius: 8px; }
-#nav b { text-transform: uppercase; font-size: 13px }
-#nav p { margin: 3px 5px 20px 5px }
-#nav p a, #nav p i { padding: 3px 5px; font-size: 13px; font-style: normal; text-decoration: none;}
-#nav p a:hover, #nav p i { background: #cde; border-radius: 5px }
-#nav ul { list-style-type: none; margin: 3px 10px 0 20px }
-#nav ul li a { overflow: hidden; margin-left: -10px; text-decoration: none; text-transform: capitalize }
-
-#contents { margin: 10px 0 0 0 }
-
-#footer { height: 60px; clear: both; padding: 4px 10px; color: #f8f8f8; margin: 0 0 -20px 0;
- border-top: 1px solid #888; font-size: 13px; background: url('images/gradients.png') 0 -37px repeat-x; border-radius: 0 0 8px 8px; }
-#footer a { font-size: 13px; padding: 0; color: #f8f8f8; }
-#footer a:hover { background: none; }
-
+.manpage nav { background: #f0f8ff; color: #036; float: right; padding: 8px; width: 250px; margin-bottom: 10px; border-radius: 8px; }
+.manpage nav b { text-transform: uppercase; font-size: 13px }
+.manpage nav p { margin: 3px 5px 20px 5px }
+.manpage nav p a,
+.manpage nav p i { padding: 3px 5px; font-size: 13px; font-style: normal; text-decoration: none;}
+.manpage nav p a:hover,
+.manpage nav p i { background: #cde; border-radius: 5px }
+.manpage nav ul { list-style-type: none; margin: 3px 10px 0 20px }
+.manpage nav ul li a { overflow: hidden; margin-left: -10px; text-decoration: none; text-transform: capitalize }
+.manpage nav form { margin: 0 0 10px 0 }
+.manpage nav select { width: 200px }
+.manpage nav input { width: 40px }
+
+
+pre { margin: 10px 0 0 0 }
pre, pre * { font-family: "Lucida Console", Monospace; font-size: 15px }
pre b, pre em, pre a { color: #369; font-weight: normal; text-decoration: none }
pre em { font-style: italic }
diff --git a/www/man.js b/www/man.js
index 7040c91..6e22b4b 100644
--- a/www/man.js
+++ b/www/man.js
@@ -454,29 +454,8 @@ function dsResults(hr, obj) {
));
ul.appendChild(tag('li', tag('a', {href:'#', onclick: buttonclick,
- 'data-url': '/json/tree.json?hash='+hash+';name='+name+';section='+section,
+ 'data-url': '/json/tree.json?hash='+hash,
'data-p': 'This manual page was found in the following locations.'},
'locations')));
})();
})();
-
-
-
-
-// The "more..." links on the homepage.
-(function(){
- var sys = byId('systems');
- if(!sys)
- return;
- var f = function() {
- var l = byName(this.parentNode, 'a');
- var show = hasClass(l[3], 'hidden');
- for(var i=3; i<l.length-1; i++)
- setClass(l[i], 'hidden', !show);
- setText(this, show ? '...less' : 'more...');
- return false
- };
- var l = byClass(sys, 'a', 'more');
- for(var i=0; i<l.length; i++)
- l[i].onclick = f;
-})();