summaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--doc/CREDITS67
-rw-r--r--doc/README.developers.pod189
-rw-r--r--doc/examples/checks/my-vendor/another-check.desc7
-rw-r--r--doc/examples/checks/my-vendor/some-check.desc6
-rw-r--r--doc/examples/lintianrc56
-rw-r--r--doc/examples/profiles/my-vendor/main.profile18
-rw-r--r--doc/examples/tags/m/missing-build-depends-on-my-vendor-tools.desc5
-rw-r--r--doc/examples/tags/m/missing-some-important-file.desc5
-rw-r--r--doc/lintian.rst992
-rw-r--r--doc/releases.md137
-rw-r--r--doc/tutorial/Lintian/Tutorial.pod39
-rw-r--r--doc/tutorial/Lintian/Tutorial/TestSuite.pod115
-rw-r--r--doc/tutorial/Lintian/Tutorial/WritingChecks.pod442
-rw-r--r--doc/tutorial/Lintian/Tutorial/WritingTests.pod539
14 files changed, 2617 insertions, 0 deletions
diff --git a/doc/CREDITS b/doc/CREDITS
new file mode 100644
index 0000000..e57c9ed
--- /dev/null
+++ b/doc/CREDITS
@@ -0,0 +1,67 @@
+In addition to those who have contributed substantial pieces of code
+(they are already listed in the copyright file), Lintian has benefited
+greatly from advice and comments by many people:
+
+ Joey Hess <joeyh@master.debian.org>
+ James A. Treacy <treacy@debian.org>
+ Ray Dassen <jdassen@wi.leidenuniv.nl>
+ Yann Dirson <dirson@debian.org>
+ Darren Stalder <torin@daft.com>
+ Topi Miettinen <Topi.Miettinen@ml.tele.fi>
+ Gregor Hoffleit <flight@debian.org>
+ Santiago Vila <sanvila@ctv.es>
+ Holger Rusch
+ Joost Witteveen <joostje@debian.org>
+ James R. Van Zandt <jrv@vanzandt.mv.com>
+ Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ Giuliano P Procida <gpp10@cam.ac.uk>
+ Michael Meskes <meskes@debian.org>
+ Christian Leutloff <leutloff@debian.org>
+ James Troup <james@nocrew.org>
+ Gregory S. Stark <gsstark@mit.edu>
+ Gordon Russell <gor@dcs.napier.ac.uk>
+ Adam P. Harris <aph@debian.org>
+ Fabrizio Polacco <fpolacco@debian.org>
+ Dirk Eddelbuettel <edd@debian.org>
+ Robert S. Edmonds <edmonds@freewwweb.com>
+ Roderick Schertler <roderick@argon.org>
+ Juan Cespedes <cespedes@debian.org>
+ Manoj Srivasta <srivasta@debian.org>
+ Oliver Elphick <Oliver.Elphick@lfix.co.uk>
+ Joel Klecker "Espy" <jk@espy.org>
+ Rob Browning <rlb@cs.utexas.edu>
+ Martin Schulze "Joey" <joey@debian.org>
+ Adrian Bridgett <adrian.bridgett@poboxes.com>
+ Marcus Brinkmann <brinkmds@rz.ruhr-uni-bochum.de>
+ Ruud de Rooij <ruud@debian.org>
+ Johnie Ingram <johnie@debian.org>
+ Brian Bassett <brianb@debian.org>
+ Charles Briscoe-Smith <cpbs@debian.org>
+ Julian Gilbey <jdg@maths.qmw.ac.uk>
+ Raphael Geissert <atomo64@gmail.com>
+ Adam D. Barratt <adam@adam-barratt.org.uk>
+ Charles Plessy <plessy@debian.org>
+ Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+ Mathieu Parent <math.parent@gmail.com>
+ Jan Wagner <waja@cyconet.org>
+ Samuel Bronson <naesten@gmail.com>
+ Don Armstrong <don@debian.org>
+ Helmut Grohne <helmut@subdivi.de>
+ Guillem Jover <guillem@debian.org>
+ Marcelo Jorge Vieira <metal@alucinados.com>
+ Anders Jonsson <anders.jonsson@norsjovallen.se>
+ Piotr Ożarowski <piotr@debian.org>
+ Ivo De Decker <ivo.dedecker@ugent.be>
+ Tomasz Buchert <tomasz.buchert@inria.fr>
+ Paul Wise <pabs@debian.org>
+ Salvatore Bonaccorso <carnil@debian.org>
+ Niklas Fiekas <niklas.fiekas@tu-clausthal.de>
+ Damyan Ivanov <dmn@debian.org>
+ Sylvestre Ledru <sylvestre@debian.org>
+ Simon McVittie <smcv@debian.org>
+ Johannes Schauer <j.schauer@email.de>
+ Matt Kraai <kraai@ftbfs.org>
+ Chris Lamb <lamby@debian.org>
+
+And of course the entire Debian Project, without which Lintian would
+have no raison to etre!
diff --git a/doc/README.developers.pod b/doc/README.developers.pod
new file mode 100644
index 0000000..640f629
--- /dev/null
+++ b/doc/README.developers.pod
@@ -0,0 +1,189 @@
+# -*- pod -*-
+#
+# Use "perldoc doc/README.developers.pod" to read it like a manpage.
+
+=head1 NAME
+
+README.developers.pod -- README file for developers of Lintian
+
+=head1 SYNOPSIS
+
+This document aims to give an overview of the Lintian internals
+and is intended for people, who wants to develop or work on Lintian.
+
+For how to use Lintian, please refer to the (other) README, the manual
+page lintian(1) or the User Manual.
+
+=head1 DESCRIPTION
+
+Lintian dissects Debian packages and tries to find bugs and policy
+violations. It contains automated checks for many aspects of Debian
+policy as well as some checks for common errors.
+
+This document describes how you can contribute to Lintian's
+development as well as adapt it to your needs.
+
+Lintian has a large code base which has as its starting point the
+directory "bin". This directory holds the "lintian" executable.
+This is what gets called when a user calls lintian. This frontend
+then calls the lintian checks which run over the Debian package
+that Lintian is checking.
+
+=head2 The source code layout
+
+The source code is divided into self-contained groups. Here is a
+quick overview.
+
+=over 4
+
+=item checks
+
+contains the checks and the tag descriptions.
+
+=item collection
+
+contains unpacking scripts
+
+=item data
+
+Symlink to the data set for the Debian vendor profiles. See entry for
+vendors below.
+
+=item debian
+
+contains Debian packaging
+
+=item doc
+
+contains the User Manuals and general docs (see man/ below)
+
+=item bin
+
+contains the frontends (e.g. code installed in /usr/bin)
+
+=item lib
+
+contains Perl modules/library for common tasks.
+
+=item man
+
+contains the manpages for tools in bin/
+
+=item private
+
+various private helpers etc.
+
+=item profiles
+
+contains vendor profiles
+
+=item reporting
+
+tools/code for the lintian.d.o setup
+
+=item t
+
+the new test suite
+
+=item vendors
+
+Per vendor data sets used by checks (and Lintian::Architecture) via
+the Lintian::Data API. Data set is stored in I<vendors/profilename/data>,
+where I<profilename> is the "full name" of the profile (e.g. ubuntu/main).
+
+=back
+
+=head2 Core concepts in Lintian
+
+In Lintian there are a number of concepts (or terms), here is a list of the
+most important ones:
+
+=over 4
+
+=item Check
+
+A library checking specific aspects of a package, changes file,
+etc. which usually can emit multiple tags.
+
+=item Emit (Tag)
+
+Tag that was not suppressed and was triggered.
+
+=item Lab(oratory)
+
+The Laboratory is Lintian's private little play-ground. When Lintian
+is asked to process a package, it will generally unpack (parts of) the
+package in the laboratory. The laboratories expire as soon as Lintian
+is done with them, unless the option '--keep-lab' was specified.
+
+Note that the laboratory is usually abbreviated to "Lab".
+
+=item Overridden (Tag)
+
+Tag that was overridden by the maintainer. Usually it means that the
+maintainer believes Lintian misdiagnosed the issue. In some cases it
+is also used for tags that does not handle "corner-cases"
+
+Overridden tags are not displayed by default, but they are still
+counted in statistics. This should not be confused with "Suppressed".
+
+=item Suppressed (Tag)
+
+Tags that are suppressed cannot be emitted.
+
+Note that suppressed tags are ignored by Lintian, so they are not
+counted in statistics. Not to be confused with "Overridden".
+
+=item Tag
+
+Issue reported by Lintian.
+
+=item Test
+
+An internal test of Lintian.
+
+=back
+
+=head2 Useful tricks
+
+There is an extended description of tricks on
+L<https://wiki.debian.org/Teams/Lintian/HackersGuide>, but some of them
+are also listed here.
+
+=head3 Running lintian from the git repository
+
+Lintian was designed to be run directly from the git repository. This
+allows you to quickly test your changes on a live package. In Lintian
+2.5.18, the frontends will automatically detect when they are being
+run from a source checkout and do the right thing. Earlier versions
+need LINTIAN_BASE (or --root). The following shell snippet can be
+used for 2.5.17 and earlier:
+
+ #!/bin/sh
+ # ONLY FOR << 2.5.18~ OR EARLIER. Lintian (>= 2.5.18~) will DTRT.
+ LINTIAN_BASE="<INSERT PATH TO LINTIAN GIT DIR>"
+ export LINTIAN_BASE
+ exec "$LINTIAN_BASE/bin/lintian" "$@"
+
+Beware of two things: If LINTIAN_BASE is not set, Lintian (<< 2.5.18~)
+will attempt to use the code from the installed version (in
+/usr/share/lintian).
+
+The other issue is that Lintian needs a C.UTF-8 (or an en_US.UTF-8)
+locale. If this is absent, it may trigger some issues with some
+(e.g. manpage) checks. With libc-bin from Wheezy and Lintian 2.5.5,
+this is no longer an issue.
+
+=head2 collections and checks
+
+Collections (as the names suggests) are used to extract or/and
+structure data from a package. This data is then used by the checks
+(usually via Lintian::Collect API) to examine the package.
+
+The check may be doing the extraction (or structuring) of data itself,
+but it should generally be avoided for "heavy" tasks. Unlike checks,
+collections can (and generally are) run in parallel to improve the
+effective runtime.
+
+=cut
+
diff --git a/doc/examples/checks/my-vendor/another-check.desc b/doc/examples/checks/my-vendor/another-check.desc
new file mode 100644
index 0000000..000580e
--- /dev/null
+++ b/doc/examples/checks/my-vendor/another-check.desc
@@ -0,0 +1,7 @@
+Check-Script: my-vendor/another-check
+Author: Niels Thykier <niels@thykier.net>
+Type: binary
+Info: An example binary check
+Needs-Info: unpacked
+Tags:
+ missing-some-important-file
diff --git a/doc/examples/checks/my-vendor/some-check.desc b/doc/examples/checks/my-vendor/some-check.desc
new file mode 100644
index 0000000..40e9cd3
--- /dev/null
+++ b/doc/examples/checks/my-vendor/some-check.desc
@@ -0,0 +1,6 @@
+Check-Script: my-vendor/some-check
+Author: Niels Thykier <niels@thykier.net>
+Type: source
+Info: An example source check
+Tags:
+ missing-build-depends-on-my-vendor-tools
diff --git a/doc/examples/lintianrc b/doc/examples/lintianrc
new file mode 100644
index 0000000..31c51f2
--- /dev/null
+++ b/doc/examples/lintianrc
@@ -0,0 +1,56 @@
+# /etc/lintianrc -- Lintian configuration file
+#
+# Note, that Lintian has reasonable default values for all variables
+# specified below. Thus, you don't have to change this file unless you
+# want something special.
+#
+# Also note, that this file uses a special syntax:
+# Empty lines are allowed, comments are introduced by a hash sign (#).
+# All other lines must have the format
+# VAR=text
+# or
+# VAR="text"
+# or
+# VAR = text
+# It is allowed to use `~' and `$HOME' in the variables, but not other
+# shell/environment variables.
+
+# Enable info tags by default (--display info)
+#display-info = yes
+
+# Limit the number of parallel unpacking jobs to X (--jobs)
+#jobs = 8
+
+# Enable pedantic tags by default (--pedantic)
+#pedantic = yes
+
+# Enable experimental tags by default (--display-experimental)
+#display-experimental = yes
+
+# Enable colored output for terminal output (--color)
+#color = auto
+
+# Show overridden tags (--show-overrides)
+#show-overrides = yes
+
+# Ignore all overrides (--no-override)
+#override = no
+
+# Verbose output by default (--verbose)
+#verbose = yes
+
+# Quiet by default (--quiet)
+#quiet = yes
+
+# Use a different directory for temporary files - useful if /tmp is a
+# tmpfs with "limited" capacity.
+#TMPDIR="/var/tmp"
+
+# Suppress the listed tags (--suppress-tags)
+#suppress-tags = debian-watch-does-not-check-openpgp-signature
+
+# Suppress the tags listed in the specified file (--suppress-tags-from-file)
+#suppress-tags-from-file = /path/to/file.txt
+
+# Specify "tag per package" display limit (--tag-display-limit)
+#tag-display-limit = 42
diff --git a/doc/examples/profiles/my-vendor/main.profile b/doc/examples/profiles/my-vendor/main.profile
new file mode 100644
index 0000000..484e362
--- /dev/null
+++ b/doc/examples/profiles/my-vendor/main.profile
@@ -0,0 +1,18 @@
+# The default profile for "my-vendor"
+Profile: my-vendor/main
+# It has all the checks and settings from the "debian" profile
+Extends: debian/main
+# Add checks specific to "my-vendor"
+Enable-Tags-From-Check:
+ my-vendor/some-check,
+ my-vendor/another-check,
+# Disable a tag
+Disable-Tags: dir-or-file-in-opt
+
+# Bump severity of no-md5sums-control-file
+# and file-missing-in-md5sums and make them
+# non-overridable
+Tags: no-md5sums-control-file,
+ file-missing-in-md5sums,
+Severity: serious
+Overridable: no
diff --git a/doc/examples/tags/m/missing-build-depends-on-my-vendor-tools.desc b/doc/examples/tags/m/missing-build-depends-on-my-vendor-tools.desc
new file mode 100644
index 0000000..e43de8f
--- /dev/null
+++ b/doc/examples/tags/m/missing-build-depends-on-my-vendor-tools.desc
@@ -0,0 +1,5 @@
+Tag: missing-build-depends-on-my-vendor-tools
+Severity: serious
+Certainty: certain
+Info: The package name starts with "my-vendor-" and is missing a
+ Build-Depends on my-vendor-tools.
diff --git a/doc/examples/tags/m/missing-some-important-file.desc b/doc/examples/tags/m/missing-some-important-file.desc
new file mode 100644
index 0000000..8876e53
--- /dev/null
+++ b/doc/examples/tags/m/missing-some-important-file.desc
@@ -0,0 +1,5 @@
+Tag: missing-some-important-file
+Severity: serious
+Certainty: certain
+Info: The package is missing a very important file, which
+ is required for all packages of my-vendor.
diff --git a/doc/lintian.rst b/doc/lintian.rst
new file mode 100644
index 0000000..7fe6d18
--- /dev/null
+++ b/doc/lintian.rst
@@ -0,0 +1,992 @@
+=====================
+Lintian User's Manual
+=====================
+.. sectnum::
+.. contents::
+ :depth: 3
+
+.. _chapter-1:
+
+Introduction
+============
+
+.. _section-1.1:
+
+About Lintian
+-------------
+
+Lintian is a Debian package checker. It can be used to check binary and
+source packages for compliance with the Debian policy and for other
+common packaging errors.
+
+Lintian uses an archive directory, called laboratory, in which it stores
+information about the packages it examines. It can keep this information
+between multiple invocations in order to avoid repeating expensive
+data-collection operations. It's also possible to check the complete
+Debian archive for bugs — in a timely manner.
+
+.. _section-1.2:
+
+The intention of Lintian
+------------------------
+
+Packaging has become complicated—not because dpkg is complicated
+(indeed, dpkg-deb is very simple to use) but because of the high
+requirements of our policy. If a developer releases a new package, she
+has to consider hundreds of guidelines to make the package \`policy
+compliant.'
+
+All parts of our policy have been introduced by the same procedure: Some
+developer has a good idea how to make packages more \`unique' with
+respect to a certain aspect—then the idea is discussed and a policy
+proposal is prepared. If we have a consensus about the policy change,
+it's introduced in our manuals.
+
+Therefore, our policy is *not* designed to make life harder for the
+maintainers! The intention is to make Debian the best Linux distribution
+out there. With this in mind, lots of policy changes are discussed on
+the mailing lists each week.
+
+But changing the policy is only a small part of the story: Just having
+some statement included in the manual does not make Debian any better.
+What's needed is for that policy to become \`real life,' i.e., it's
+*implemented* in our packages. And this is where Lintian comes in:
+Lintian checks packages and reports possible policy violations. (Of
+course, not everything can be checked mechanically — but a lot of
+things can and this is what Lintian is for.)
+
+Thus, Lintian has the following goals:
+
+- *To give us some impression of the \`gap' between theory (written
+ policy) and praxis (current state of implementation).*
+
+ From the results of the first two Lintian checks I implemented, I see
+ that there is a big need to make this gap smaller. Introducing more
+ policy aspects is worthless unless they are implemented. We first
+ should fix packages to comply with current policy before searching
+ for new ways to make policy more detailed. (Of course, there are also
+ important policy changes that need to be introduced — but this is
+ not what's meant here.)
+
+- *To make us re-think about certain aspects of our policy.*
+
+ For example, it could turn out that some ideas that once sounded
+ great in theory are hard to implement in all our packages — in
+ which case we should rework this aspect of policy.
+
+- *To show us where to concentrate our efforts in order to make Debian
+ a higher quality distribution.*
+
+ Most release requirements will be implemented through policy. Lintian
+ reports provide an easy way to compare *all* our packages against
+ policy and keep track of the fixing process by watching bug reports.
+ Note, that all this can be done *automatically*.
+
+- *To make us avoid making the same mistakes all over again.*
+
+ Being humans, it's natural for us to make errors. Since we all have
+ the ability to learn from our mistakes, this is actually no big
+ problem. Once an important bug is discovered, a Lintian check could
+ be written to check for exactly this bug. This will prevent the bug
+ from appearing in any future revisions of any of our packages.
+
+.. _section-1.3:
+
+Design issues
+-------------
+
+There are three fields of application for Lintian:
+
+- one person could use Lintian to check the whole Debian archive and
+ reports bugs,
+
+- each maintainer runs Lintian over her packages before uploading them,
+
+- dinstall checks packages which are uploaded to master before they are
+ installed in the archive.
+
+The authors of Lintian decided to use a very modular design to achieve
+the following goals:
+
+- flexibility: Lintian can be used to check single packages or the
+ whole archive and to report and keep track of bug reports, etc.
+
+- completeness: Lintian will eventually include checks for (nearly)
+ everything that can be checked mechanically.
+
+- uptodateness: Lintian will be updated whenever policy is changed.
+
+- performance: Lintian should make it possible to check single packages
+ within seconds or check the full archive within 5 days.
+
+The design also has a number of constrains that limits the things
+Lintian can check for and what tools it can use:
+
+- static analysis: The code in a package may be analyzed, but it should
+ *never* be executed. However, Lintian can (and does) use external
+ tools to analyze files in the package.
+
+- deterministic replay-ability: Checks should not rely on the state of
+ system caches or even the system time. These things makes it harder
+ for others to reproduce (the absence of) tags.
+
+- same source analysis: Lintian checks packages in small isolated
+ groups based on the source package. Requiring the presence of all the
+ dependencies to provide the full results make it harder to run
+ lintian (not to mention, it makes "deterministic replay-ability" a
+ lot harder as well).
+
+.. _section-1.4:
+
+Disclaimer
+----------
+
+Here is a list of important notes on how to use Lintian:
+
+1. Lintian is not finished yet and will probably never be. Please don't
+ use Lintian as a reference for Debian policy. Lintian might miss a
+ lot of policy violations while it might also report some violations
+ by mistake. If in doubt, please check out the policy manuals.
+
+2. The Debian policy gives the maintainers a lot of freedom. In most
+ cases, the guidelines included in the manuals allow exceptions. Thus,
+ if Lintian reports a policy violation on a package and you think this
+ is such an exception (or if you think Lintian has a bug) you can do
+ two things: If your package is a bit non-standard and weird in this
+ regard, you can install an override. If you think however that the
+ check is too easily or outright wrongly triggered, please file a bug
+ on the lintian package.
+
+3. Please DO NOT use Lintian to file bug reports (neither single ones
+ nor mass bug reports). This is done by the authors of Lintian already
+ and duplication of efforts and bug reports should be avoided! If you
+ think a certain bug is \`critical' and should be reported/fixed
+ immediately, please contact the maintainer of the corresponding
+ package and/or the Lintian maintainers.
+
+4. Any feedback about Lintian is welcome! Please send your comments to
+ the lintian maintainers lintian-maint@debian.org.
+
+.. _chapter-2:
+
+Getting started
+===============
+
+.. _section-2.1:
+
+Installing Lintian
+------------------
+
+Before you can start to check your packages with Lintian, you'll have to
+install the lintian Debian package.
+
+Alternatively you can checkout Lintian from the source repository and
+use that directly. By setting LINTIAN_BASE (or using the --root option)
+lintian can be run from the source directory as if it had been installed
+on your system.
+
+The only known caveat of using Lintian from the source directory is that
+Lintian requires a C.UTF-8 (or en_US.UTF-8) locale to correctly process
+some files. (Is that still true?)
+
+.. _section-2.2:
+
+Running lintian
+---------------
+
+After that, you can run Lintian on a changes file or any Debian binary,
+udeb or source packages like this:
+
+::
+
+ $ lintian etm_3.2.30-1.1_all.deb
+ E: etm: appstream-metadata-legacy-format [usr/share/appdata/etm.appdata.xml]
+ W: etm: appstream-metadata-in-legacy-location [usr/share/appdata/etm.appdata.xml]
+ I: etm: package-contains-documentation-outside-usr-share-doc [usr/share/etm/etmTk/help/UserManual.html]
+ $
+
+Please note that some checks are cross-package checks and can only be
+(accurately) performed if the binary packages and the source are
+processed together. If Lintian is passed a changes file, it will attempt
+to process all packages listed in the changes file.
+
+Lintian supports a number of command line options, which are documented
+in the manpage of lintian(1). Some of the options may appear in the
+lintianrc file without leading dashes.
+
+.. _section-2.3:
+
+Lintian Tags
+------------
+
+Lintian uses a special format for all its error and warning messages.
+With that it is very easy to write other programs which run Lintian and
+interpret the displayed messages.
+
+The first character of each line indicates the type of message.
+Currently, the following types are supported:
+
+*Errors (E)*
+ The displayed message indicates a policy violation or a packaging
+ error. For policy violations, Lintian will cite the appropriate
+ policy section when it is invoked with the ``-i`` option.
+
+*Warnings (W)*
+ The displayed message might be a policy violation or packaging error.
+ A warning is usually an indication that the check is known to
+ sometimes produce false positive alarms, because either the
+ corresponding rule in policy has many exceptions or the check uses
+ some sort of heuristic to find errors.
+
+*Info (I)*
+ The displayed message is meant to inform the maintainer about a
+ certain packaging aspect. Such messages do not usually indicate
+ errors, but might still be of interest to the curious. They are not
+ displayed unless the ``-I`` option is set.
+
+*Notes (N)*
+ The displayed message is a debugging message which informs you about
+ the current state of Lintian.
+
+*Experimental (X)*
+ The displayed message is one of the types listed above, but has been
+ flagged as \`experimental' by the Lintian maintainers. This means
+ that the code that generates this message is not as well tested as
+ the rest of Lintian, and might still give surprising results. Feel
+ free to ignore Experimental messages that do not seem to make sense,
+ though of course bug reports are always welcome. They are not
+ displayed unless the ``-E`` option is set.
+
+*Overridden (O)*
+ The displayed message indicates a previous *Warning* or *Error*
+ message which has been *overridden* (see below). They are not
+ displayed unless the ``--show-overrides`` option is set.
+
+*Pedantic (P)*
+ The displayed message indicates a message of Lintian at its most
+ pickiest and include checks for particular Debian packaging styles,
+ checks that are very frequently wrong, and checks that many people
+ disagree with. They are not displayed unless the ``--pedantic``
+ option is set.
+
+The type indicator is followed by the name of the package and for
+non-binary packages the type of the package. Then comes the *problem*
+that was discovered, also known as a *tag* (for example,
+``old-fsf-address-in-copyright-file``).
+
+Depending on which tag has been reported, the line may contain
+additional arguments which tell you, for example, which files are
+involved.
+
+If you do not understand what a certain tag is about, you can specify
+the ``-i`` option when calling Lintian to get a detailed description of
+the reported tags:
+
+::
+
+ $ lintian --info --tags appstream-metadata-in-legacy-location etm_3.2.30-1.1_all.deb
+ N:
+ W: etm: appstream-metadata-in-legacy-location [usr/share/appdata/etm.appdata.xml]
+ N:
+ N: AppStream metadata file was found in /usr/share/appdata/. The AppStream XML files should be placed in /usr/share/metainfo/.
+ N:
+ N: Please refer to https://wiki.debian.org/AppStream/Guidelines for details.
+ N:
+ N: Visibility: warning
+ N: Show-Always: no
+ N: Check: appstream-metadata
+ N:
+ $
+
+In some cases, the messages contain some additional text with a leading
+hash character (``#``). This text should be ignored by any other
+programs which interpret Lintian's output because it doesn't follow a
+unique format between different messages and it's only meant as
+additional information for the maintainer.
+
+.. _section-2.4:
+
+Overrides
+---------
+
+In some cases, the checked package does not have a bug or does not
+violate policy, but Lintian still reports an error or warning. This can
+have the following reasons: Lintian has a bug itself, a specific Lintian
+check is not smart enough to know about a special case allowed by
+policy, or the policy does allow exceptions to some rule in general.
+
+In the first case (where Lintian has a bug) you should send a bug report
+to the Debian bug tracking system and describe which package you
+checked, which messages have been displayed, and why you think Lintian
+has a bug. Best would be, if you would run Lintian again over your
+packages using the ``-d`` (or ``--debug``) option, which will cause
+Lintian to output much more information (debugging info), and include
+these messages in your bug report. This will simplify the debugging
+process for the authors of Lintian.
+
+In the other two cases (where the error is actually an exception to
+policy), you should probably add an override. If you're unsure though
+whether it's indeed a good case for an override, you should contact the
+Lintian maintainers too, including the Lintian error message and a short
+note, stating why you think this is an exception. This way, the Lintian
+maintainers can be sure the problem is not actually a bug in Lintian or
+an error in the author's reading of policy. Please do not override bugs
+in lintian, they should rather be fixed than overridden.
+
+Once it has been decided that an override is needed, you can easily add
+one by supplying an overrides file. If the override is for a binary or
+udeb package, you have to place it at
+``/usr/share/lintian/overrides/<package>`` inside the package. The tool
+``dh_lintian`` from the Debian package debhelper may be useful for this
+purpose.
+
+If the override is for a source package, you have to place it at
+``debian/source/lintian-overrides`` or
+``debian/source.lintian-overrides`` (the former path is preferred). With
+that, Lintian will know about this exception and not report the problem
+again when checking your package. (Actually, Lintian will report the
+problem again, but with type *overridden*, see above.)
+
+Note that Lintian extracts the override file from the (u)deb and stores
+it in the laboratory. The files currently installed on the system are
+not used in current Lintian versions.
+
+.. _section-2.4.1:
+
+Format of override files
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+The format of the overrides file is simple, it consists of one override
+per line (and may contain empty lines and comments, starting with a
+``#``, on others): ``[[<package>][ <archlist>][ <type>]: ]<lintian-tag>[
+[*]<context>[*]]``. <package> is the package name;
+<archlist> is an architecture list (see Architecture specific overrides
+for more info); <type> is one of ``binary``, ``udeb`` and ``source``,
+and <context> is all additional information provided by Lintian
+except for the tag. What's inside brackets is optional and may be
+omitted if you want to match it all. Additionally, if the context of
+the tag contains paths to files in the package, they're enclosed with
+literal brackets (so called "pointed hints") so that tools which
+process lintian tags can link to the according file and potentially
+even line in the file.
+
+An example file for a binary package would look like:
+
+::
+
+ /usr/share/lintian/overrides/foo, where foo is the name of your package
+
+ # We use a non-standard dir permission to only allow the webserver to look
+ # into this directory:
+ foo binary: non-standard-dir-perm
+ foo binary: FSSTND-dir-in-usr [/usr/man/man1/foo.1.gz]
+
+An example file for a source package would look like:
+
+::
+
+ debian/source/lintian-overrides in your base source directory
+ foo source: debian-files-list-in-source
+ # Upstream distributes it like this, repacking would be overkill though, so
+ # tell lintian to not complain:
+ foo source: configure-generated-file-in-source [config.cache]
+
+Many tags can occur more than once (e.g. if the same error is found in
+more than one file). You can override a tag either completely by
+specifying its name (first line in the examples) or only one occurrence
+of it by specifying the additional info, too (second line in the
+examples). If you add an asterisk (``*``) in the additional info, this
+will match arbitrary strings similar to the shell wildcard. For example:
+
+::
+
+ # Multiple files need to be covered by the override
+ source-is-missing [apidoc/html/*.js]
+
+.. _section-2.4.2:
+
+Documenting overrides
+~~~~~~~~~~~~~~~~~~~~~
+
+To assist reviewers, Lintian will extract the comments from the
+overrides file and display the related comments next to the overridden
+tags.
+
+Comments directly above an override will be shown next to all tags it
+overrides. If an override for the same tags appears on the very next
+line, it will inherit the comment from the override above it.
+
+::
+
+ # This comment will be shown above all tags overridden by the following
+ # two overrides, (because they apply to the same tag and there is no
+ # empty line between them)
+ foo source: some-tag exact match
+ foo source: some-tag wildcard * match
+ # This override has its own comment, and it is not shared with the
+ # override below (because there is an empty line in between them).
+ foo source: some-tag another exact match
+
+ foo source: some-tag override without a comment
+
+Empty lines can be used to disassociate a comment from an override
+following it. This can also be used to make a general comment about the
+overrides that will not be displayed.
+
+::
+
+ # This is a general comment not connected to any override, since there
+ # is one (or more) empty lines after it.
+
+ foo source: another-tag without any comments
+
+.. _section-2.4.3:
+
+Architecture specific overrides
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In rare cases, Lintian tags may be architecture specific. It is possible
+to mark overrides architecture specific by using the optional
+architecture list.
+
+The architecture list has the same syntax as the architecture list in
+the "Build-Depends" field of a source package. This is described in
+detail in the `Debian Policy Manual
+§7.1 <https://www.debian.org/doc/debian-policy/#s-controlsyntax>`__.
+Examples:
+
+::
+
+ # This is an example override that only applies to the i386
+ # architecture.
+ foo [i386] binary: some-tag optional-extra
+
+ # An architecture wildcard would look like:
+ foo [any-i386] binary: another-tag optional-extra
+
+ # Negation also works
+ foo [!amd64 !i386] binary: some-random-tag optional-extra
+
+ # Negation even works for wildcards
+ foo [!any-i386] binary: some-tag-not-for-i386 optional-extra
+
+ # The package name and the package type is optional, so this
+ # also works
+ [linux-any]: tag-only-for-linux optional-extra.
+
+An unknown architecture will trigger a packaging hint. So will an
+architecture-specific override in an architecture-independent
+installable.
+
+.. _section-2.5:
+
+Vendor Profiles
+---------------
+
+Vendor profiles allows vendors and users to customize Lintian without
+having to modify the underlying code. If a profile is not explicitly
+given, Lintian will derive the best possible profile for the current
+vendor from dpkg-vendor.
+
+.. _section-2.5.1:
+
+Rules for profile names and location
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Profile names should only consist of the lower case characters ([a-z]),
+underscore (_), dash (-) and forward slashes (/). Particularly note that
+dot (.) are specifically *not* allowed in a profile name.
+
+The default profile for a vendor is called ``$VENDOR/main``. If Lintian
+sees a profile name without a slash, it is taken as a short form of the
+default profile for a vendor with that name.
+
+The filename for the profile is derived from the name by simply
+concatenating it with ``.profile``, Lintian will then look for a file
+with that name in the following directories:
+
+- ``$XDG_DATA_HOME/lintian/profiles``
+
+- ``$HOME/.lintian/profiles``
+
+- ``/etc/lintian/profiles``
+
+- ``$LINTIAN_BASE/profiles``
+
+Note that an implication of the handling of default vendor profiles
+implies that profiles must be in subdirectories of the directories above
+for Lintian to recognise them.
+
+The directories are checked in the listed order and the first file
+matching the profile will be used. This allows users to override a
+system profile by putting one with the same filename in
+``$XDG_DATA_HOME/lintian/profiles`` or ``$HOME/.lintian/profiles``.
+
+.. _section-2.5.2:
+
+Profile syntax and semantics
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Profiles are written in the same syntax as Debian control files as
+described in the `Debian Policy Manual
+§5.1 <https://www.debian.org/doc/debian-policy/#s-controlsyntax>`__.
+Profiles allow comments as described in the Policy Manual.
+
+.. _section-2.5.2.1:
+
+Main profile paragraph
+^^^^^^^^^^^^^^^^^^^^^^
+
+The fields in the first paragraph are:
+
+*Profile* (simple, mandatory)
+ Name of the profile.
+
+*Extends* (simple, optional)
+ Name of the (parent) profile, which this profile extends. Lintian
+ will recursively process the extended profile before continuing with
+ processing this profile. In the absence of this field, the profile is
+ not based on another profile.
+
+*Load-Checks* (folded, optional)
+ Comma-separated list of checks. Lintian will ensure all checks listed
+ are loaded (allowing tags from them to be enabled or disabled via
+ Enable-Tags or Disable-Tags).
+
+ If a given check was already loaded before this field is processed,
+ then it is silently ignored. Otherwise, the check is loaded and all
+ of its tags are disabled (as if it had been listed in
+ Disable-Tags-From-Check).
+
+ This field is most likely only useful if the profile needs to enable
+ a list of tags from a check in addition to any tags already enabled
+ from that check (if any).
+
+*Enable-Tags-From-Check* (folded, optional)
+ Comma-separated list of checks. All tags from each check listed will
+ be enabled in this profile. The check will be loaded if it wasn't
+ already.
+
+*Disable-Tags-From-Check* (folded, optional)
+ Comma-separated list of checks. All tags from each check listed will
+ be disabled in this profile. The check will be loaded if it wasn't
+ already.
+
+*Enable-Tags* (folded, optional)
+ Comma-separated list of tags that should be enabled. It may only list
+ tags from checks already loaded or listed in one of the following
+ fields "Load-Checks", "Enable-Tags-From-Check" or
+ "Disable-Tags-From-Check" in the current profile.
+
+*Disable-Tags* (folded, optional)
+ Comma-separated list of tags that should be disabled. It may only
+ list tags from checks already loaded or listed in one of the
+ following fields "Load-Checks", "Enable-Tags-From-Check" or
+ "Disable-Tags-From-Check" in the current profile.
+
+The profile is invalid and is rejected, if Enable-Tags and Disable-Tags
+lists the same tag twice - even if it is in the same field. This holds
+analogously for checks and the three fields Load-Checks,
+Enable-Tags-From-Check and Disable-Tags-From-Check.
+
+It is allowed to list a tag in Enable-Tags or Disable-Tags even if the
+check that provides this tag is listed in the Disable-Tags-From-Check or
+Enable-Tags-From-Check field. In case of conflict, Enable-Tags /
+Disable-Tags shall overrule Disable-Tags-From-Check /
+Enable-Tags-From-Check within the profile.
+
+Load-Checks, Enable-Tags-From-Check and Disable-Tags-From-Check can be
+used to load third-party or vendor specific checks.
+
+It is not an error to load, enable or disable a check or tag that is
+already loaded, enabled or disabled respectively (e.g. by a parent
+profile).
+
+A profile is invalid if it directly or indirectly extends itself or if
+it extends an invalid profile.
+
+By default the tags from the check "lintian" will be loaded as they
+assist people in writing and maintaining their overrides file (e.g. by
+emitting ``malformed-override``). However, they can be disabled by
+explicitly adding the check ``lintian`` in the Disable-Tags-From-Check
+field.
+
+.. _section-2.5.2.2:
+
+Tag alteration paragraphs
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The fields in the secondary paragraphs are:
+
+*Tags* (folded, mandatory)
+ Comma separated list of tags affected by this paragraph.
+
+*Overridable* (simple, optional)
+ Either "Yes" or "No", which decides whether these tags can be
+ overridden. Lintian will print an informal message if it sees an
+ override for a tag marked as non-overridable (except if --quiet is
+ passed).
+
+*Visibility* (simple, optional)
+ The value must be a valid tag visibility other than "classification".
+ The visibility of the affected tags is set to this value. This cannot
+ be used on any tag that is defined as a "classification" tag.
+
+ Note that *experimental* is not a visibility.
+
+The paragraph must contain at least one other field than the Tag field.
+
+.. _section-2.5.2.3:
+
+An example vendor profile
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Below is a small example vendor profile for a fictive vendor called
+"my-vendor".
+
+::
+
+ # The default profile for "my-vendor"
+ Profile: my-vendor/main
+ # It has all the checks and settings from the "debian" profile
+ Extends: debian/main
+ # Add checks specific to "my-vendor"
+ Enable-Tags-From-Check:
+ my-vendor/some-check,
+ my-vendor/another-check,
+ # Disable a tag
+ Disable-Tags: dir-or-file-in-opt
+
+ # Bump visibility of no-md5sums-control-file
+ # and file-missing-in-md5sums and make them
+ # non-overridable
+ Tags: no-md5sums-control-file,
+ file-missing-in-md5sums,
+ Visibility: error
+ Overridable: no
+
+.. _section-2.6:
+
+Vendor specific data files
+--------------------------
+
+Lintian uses a number of data files for various checks, ranging from
+common spelling mistakes to lists of architectures. While some of these
+data files are generally applicable for all vendors (or Debian
+derivatives), others are not.
+
+Lintian supports vendor specific data files. This allows vendors to deploy
+their own data files tailored for their kind of system. Lintian supports
+both extending an existing data file and completely overriding it.
+
+.. _section-2.6.1:
+
+Load paths and order
+~~~~~~~~~~~~~~~~~~~~
+
+Lintian will search the following directories in order for vendor
+specific data files:
+
+- ``$XDG_DATA_HOME/lintian/vendors/PROFILENAME/data``
+
+- ``$HOME/.lintian/vendors/PROFILENAME/data``
+
+- ``/etc/lintian/vendors/PROFILENAME/data``
+
+- ``$LINTIAN_BASE/vendors/PROFILENAME/data``
+
+If none of the directories exists or none of them provide the data file
+in question, Lintian will (recursively) retry with the parent of the
+vendor (if any). If the vendor and none of its parents provide the data
+file, Lintian will terminate with an error.
+
+.. _section-2.6.2:
+
+Basic syntax of data files
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Generally, data files are read line by line. Leading whitespace of every
+line is removed and (now) empty lines are ignored. Lines starting with a
+``#`` are comments and are also ignored by the parser. Lines are
+processed in the order they are read.
+
+If the first character of the line is a ``@``, the first word is parsed
+as a special processing instruction. The rest of the line is a parameter
+to that processing instruction. Please refer to `List of processing
+instructions <#section-2.6.2.1>`__.
+
+All other lines are read as actual data. If the data file is a table (or
+map), the lines will parsed as key-value pairs. If the data file is a
+list (or set), the full line will be considered a single value of the
+list.
+
+It is permissible to define the same key twice with a different value.
+In this case, the value associated with the key is generally redefined.
+There are very rare exceptions to this rule, where the data file is a
+table of tables (of values). In this case, a recurring key is used to
+generate the inner table.
+
+.. _section-2.6.2.1:
+
+List of processing instructions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following processing instructions are recognised:
+
+*@delete ENTRY*
+ Removes a single entry denoted by ENTRY that has already been parsed.
+
+ It is permissible to list a non-existent entry, in which case the
+ instruction has no effect. This instruction does *not* prevent the
+ entry from being (re-)defined later, it only affects the current
+ definition of the entry.
+
+ For key-pair based data files, ENTRY must match the key. For single
+ value data files, ENTRY must match the line to remove.
+
+*@include-parent*
+ Processes parent data file of the current data file.
+
+ The informal semantics of this instruction is that it reads the
+ "next" data file in the vendor "chain". The parsing of the parent is
+ comparable to a C-style include or sourcing a shell script.
+
+ More formally, let CP be the name of the vendor profile that defines
+ the data file containing the instruction. Let the parent of CP be
+ referred to as PCP.
+
+ Lintian will search for the data file provided by PCP using the rules
+ as specified in `Load paths and order <#section-2.6.1>`__. If no data
+ file is found, Lintian will terminate the parsing with an error.
+ Thus, this instruction can only be used by profiles that extends
+ other profiles.
+
+.. _chapter-3:
+
+Advanced usage
+==============
+
+.. _section-3.1:
+
+How Lintian works
+-----------------
+
+Lintian is divided into the following layers:
+
+*frontend*
+ the command line interface (currently, this layer consists of the
+ ``lintian`` program.
+
+*checks*
+ a set of modules that check different aspects of packages.
+
+*data collectors*
+ a set of scripts that prepares specific information about a package
+ needed by the check modules
+
+When you check a package with Lintian, the following steps are performed
+(not exactly in this order—but the details aren't important now):
+
+1. An entry is created for the package in the *laboratory* (or just
+ *lab*).
+
+2. Some data is collected about the package. (That is done by the
+ so-called *data collector* scripts.) For example, the ``file``
+ program is run on each file in the package and the output is stored
+ in the lab.
+
+3. The *checks* are run over the package and report any discovered
+ policy violations or other errors. These scripts don't access the
+ package contents directly, but use the collected data as input.
+
+4. Depending on the *lab mode* Lintian uses (see below), the whole lab
+ directory is removed again. If the lab is not removed, parts of the
+ data collected may be auto cleaned to reduce disk space.
+
+This separation of the *check* from the *data collector scripts* makes
+it possible to run Lintian several times over a package without having
+to recollect all the data each time. In addition, the checker scripts do
+not have to worry about packaging details since this is abstracted away
+by the collector scripts.
+
+.. _section-3.2:
+
+The laboratory
+--------------
+
+Lintian creates a temporary lab in ``/tmp`` which is removed again after
+Lintian has completed its checks, unless the ``--keep-lab`` is used.
+
+.. _section-3.3:
+
+Writing your own Lintian checks
+-------------------------------
+
+This section describes how to write and deploy your own Lintian checks.
+Lintian will load checks from the following directories (in order):
+
+- ``$LINTIAN_BASE/checks``
+
+Existing checks can be shadowed by placing a check with the same name in
+a directory appearing earlier in the list. This also holds for the
+checks provided by Lintian itself.
+
+Checks in Lintian consist of a Perl module implementing the actual check
+(.pm). The files names of such checks are expected to be in CamelCase. For
+the check name used on the command line, case transitions are replaced with
+hyphens. Perl's two colons (::) are replaced with a slash.
+
+Vendors are recommended to use their vendor name before the first slash
+(e.g. "ubuntu/fields").
+
+.. _section-3.3.1:
+
+Check description file
+~~~~~~~~~~~~~~~~~~~~~~
+
+The check description file is written in the same syntax as Debian
+control files as described in the `Debian Policy Manual
+§5.1 <https://www.debian.org/doc/debian-policy/#s-controlsyntax>`__.
+Check description files allow comments as described in the Policy
+Manual.
+
+The check description file has two paragraph types. The first is the
+check description itself and must be the first paragraph. The rest of
+the descriptions describe tags, one tag per paragraph.
+
+.. _section-3.3.1.1:
+
+Check description paragraph
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The fields in the check description paragraph are:
+
+*Check-Script* (simple, mandatory)
+ Name of the check. This is used to determine the package name of the
+ Perl module implementing the check.
+
+*Type* (simple, mandatory)
+ Comma separated list of package types for which this check should be
+ run. Allowed values in the list are "binary" (.deb files), "changes"
+ (.changes files), "source" (.dsc files) and "udeb" (.udeb files).
+
+*Info* (multiline, optional)
+ A short description of what the check is for.
+
+*Author* (simple, optional)
+ Name and email of the person, who created (or implemented etc.) the
+ check.
+
+*Abbrev* (simple, optional)
+ Alternative or abbreviated name of the check. These can be used with
+ certain command line options as an alternative name for the check.
+
+.. _section-3.3.1.2:
+
+Tag description paragraph
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The fields in the tag description paragraph are:
+
+*Tag* (simple, mandatory)
+ Name of the tag. It must consist entirely of the lower or/and upper
+ case characters ([a-zA-Z]), digits ([0-9]), underscore (_), dash (-)
+ and period (.). The tag name should be at most 68 characters long.
+
+*Severity* (simple, mandatory)
+ Determines the default value for the alert level. The value must be
+ one of "error", "warning", "info", "pedantic", or "classification".
+ This correlates directly to the one-letter code (of non-experimental
+ tags).
+
+*Info* (multiline, mandatory)
+ The tag descriptions can be found on Lintian's website
+ ("https://lintian.debian.org"). The description is in the standard
+ Markdown format.
+
+ The symbols &, < and > must be escaped as &amp;, &lt; and &gt;
+ (respectively). Please also escape _ as &lowbar; and * as &ast;.
+
+ Indented lines are considered "pre-formatted" and will not be line
+ wrapped. These lines are still subject to the allowed HTML tags and
+ above mentioned escape sequences.
+
+*Ref* (simple, optional)
+ A comma separated list of references. It can be used to refer to
+ extra documentation. It is primarily used for manual references, HTTP
+ links or Debian bug references.
+
+ If a reference contains a space, it is taken as a manual reference
+ (e.g. "policy 4.14"). These references are recorded in the
+ "output/manual-references" data file.
+
+ Other references include manpages ("lintian(1)"), ftp or http(s)
+ links ("https://lintian.debian.org"), file references
+ ("/usr/share/doc/lintian/changelog.gz") or Debian bug numbers
+ prefixed with a hash ("#651816").
+
+ Unknown references are (silently) ignored.
+
+*Experimental* (simple, optional)
+ Whether or not the tag is considered "experimental". Recognised
+ values are "no" (default) and "yes". Experimental tags always use "X"
+ as their "one-letter" code.
+
+.. _section-3.3.2:
+
+Check Perl module file
+~~~~~~~~~~~~~~~~~~~~~~
+
+This section describes the requirements for the Perl module implementing
+a given check.
+
+The Perl package name of the check must be identical to the check name
+(as defined by the "Check-Script" field in the description file) with
+the following transformations:
+
+- All periods and dashes are replaced with underscores.
+
+- All forward slashes are replaced by two colons (::).
+
+- The resulting value is prefixed with "Lintian::".
+
+As an example, the check name ``contrib/hallo-world`` will result in the
+Perl package name ``Lintian::contrib::hallo_world``.
+
+.. _section-3.3.2.1:
+
+API of the "run" sub
+^^^^^^^^^^^^^^^^^^^^
+
+The Perl module must implement the sub called ``run`` in that Perl
+package. This sub will be run once for each package to be checked with 5
+arguments. These are (in order):
+
+- The package name.
+
+- The package type being checked in this run. This string is one of
+ "binary" (.deb), "changes" (.changes), "source" (.dsc) or "udeb"
+ (.udeb).
+
+- An instance of API Lintian::Collect. Its exact type depends on the
+ type being processed and is one of Lintian::Collect::Binary (.deb or
+ .udeb), Lintian::Collect::Changes (.changes) or
+ Lintian::Collect::Source (.dsc).
+
+- An instance of Lintian::Processable that represents the package being
+ processed.
+
+- An instance of Lintian::ProcessableGroup that represents the other
+ processables in the given group. An instance of the
+ Lintian::Collect::Group is available via its "info" method.
+
+Further arguments may be added in the future after the above mentioned
+ones. Implementations should therefore ignore extra arguments beyond the
+ones they know of.
+
+If the run sub returns "normally", the check was run successfully.
+Implementations should ensure the return value is undefined.
+
+If the run sub invokes a trappable error (e.g. "die"), no further checks
+are done on the package and Lintian will (eventually) exit with 1 to its
+caller. The check may still be run on other packages.
diff --git a/doc/releases.md b/doc/releases.md
new file mode 100644
index 0000000..7613cf9
--- /dev/null
+++ b/doc/releases.md
@@ -0,0 +1,137 @@
+Lintian release management
+==========================
+
+
+
+Preparing and doing a release
+-----------------------------
+
+Run the full test suite while the distribution is still set to
+UNRELEASED to ensure everything and all tests are green. Once
+complete, replace the placeholder in the changelog with the
+actual tags changed. The following command may be helpful:
+
+ $ private/generate-tag-summary --in-place
+
+Then set the distribution (e.g. via `dch -r`) and run the "scripts" test
+suite again. This may appear redundant at first, but some of the
+tests react differently when the distribution is not UNRELEASED
+(e.g. changelog-format checks that you remembered the step above).
+
+Build the package and run lintian on itself, cleaning up or overriding
+issues that have not been fixed during development. If you do code
+changes, remember to set the distribution back to UNRELEASED!
+Otherwise, some checks on the code will be skipped (e.g. critic).
+
+Sign and upload the package. Furthermore, prepare a signed git
+tag. This is generally done in the following way:
+
+ * Take a copy of the signed `.changes`
+ * Optionally strip the signature from it.
+ * Add a tag message to the top of the file
+ * Tag with `git tag <VERSION> -u <KEYID> --file <FILE>`
+
+This method is used to provide a "trust" path between the tag and
+the uploaded files. This is also why we use the signed `.changes`
+(as signing the source package changes the checksums in the `.changes`).
+
+Once the upload has been accepted and the commit has been tagged, you
+may want to "open" the next entry in the changelog. The rationale for
+this is that it makes tests go back to "regular" development mode. At
+the same time, the "tag-summary" reminder can be re-added. See commit
+a9c67f2 as an example of how it is done.
+
+
+To update lintian on lintian.debian.org, please see the README in
+/srv/lintian.debian.org on lintian.debian.org. NOTE: if Lintian has
+obtained any new dependencies, these must be installed by DSA before
+updating lintian.debian.org (send a patch to DSA for their metapackage
+for lintian.debian.org).
+
+
+Updating lintian.debian.org
+===========================
+
+Once a new release is done and tagged, we can update the installation
+on archive-wide processing server that generates "lintian.debian.org".
+Historically, this server was the same as "lintian.debian.org".
+However, these days the archive-wide processing happens on a separate
+server called:
+
+ lindsay.debian.org
+ (DD-accessible)
+
+In the rest of the this document, we will refer to this as the lintian-host.
+
+
+The update is done in the following steps:
+
+Step 1
+------
+
+Ensure that any new dependencies are installed. These must be
+installed by DSA before updating lintian.debian.org (send a patch to
+DSA for their metapackage for lintian.debian.org).
+
+Often there are no new dependencies meaning that this step can be
+omitted. Please remember that you can request the dependencies before
+the lintian release.
+
+Step 2
+------
+
+Login to the lintian-host and ensure that lintian is not currently
+performing an archive-wide run and that you have "plenty" of time to
+complete the upgrade. The entire upgrade can be done in less than 5
+minutes (but you may want to have a "slightly" larger window the first
+few times).
+
+You can find lintian's crontab via either:
+
+ sudo -ulintian crontab -l
+
+OR
+
+ less /srv/lintian.debian.org/etc/cron
+
+If the archive-wide run is currently active, check the harness log
+(`tail -f /srv/lintian.debian.org/logs/harness.log`).
+
+ 1. If lintian is processing packages, then send a SIGTERM to the
+ "reporting-lintian-harness" process and it will gracefully
+ terminate lintian and commit the latest changes. A few seconds
+ after the signal has been sent, reporting-lintian-harness should
+ emit something like:
+
+ [2018-01-07T14:26:25]: Signal SIGTERM acknowledged[...]
+
+ 1. If "reporting-sync-state" is running then either kill it and
+ "harness" (if you do not mind triggering an error and possible
+ cron-noise). Alternatively, wait for "reporting-lintian-harness"
+ to start and kill it once lintian starts processing packages.
+
+ 1. If "reporting-html-reports" is running, then just wait the 5-10
+ minutes it takes for the entire run to complete. Otherwise, we
+ might end up with a broken report.
+
+
+
+Now that we are sure the lintian is not running and will not start in
+the middle of the upgrade, we can perform the actual upgrade.
+
+ cd /srv/lintian.debian.org/lintian
+ # Reset the directory in case there are out of band patches
+ # - alternative being "sudo -ulintian git stash" as long as you clean it up
+ sudo -ulintian git reset --hard
+ sudo -ulintian git fetch
+ # e.g. sudo -ulintian git checkout 2.5.67
+ sudo -ulintian git checkout $LINTIAN_RELEASE_TAG
+
+ # Update the manual + manpages
+ sudo -ulintian debian/rules clean
+ sudo -ulintian debian/rules rebuild-lintian.debian.org
+
+With this, the upgrade is complete. If the reporting framework needs
+additional configuration, please remember to update
+`/srv/lintian.debian.org/config.yaml` (Note it is *not* the one in the
+reporting directory).
diff --git a/doc/tutorial/Lintian/Tutorial.pod b/doc/tutorial/Lintian/Tutorial.pod
new file mode 100644
index 0000000..3b088eb
--- /dev/null
+++ b/doc/tutorial/Lintian/Tutorial.pod
@@ -0,0 +1,39 @@
+=head1 NAME
+
+Lintian::Tutorial -- The newcomer's guide to Lintian
+
+=head1 SYNOPSIS
+
+Getting started with lintian in 5 minutes... maybe 10.
+
+=head1 DESCRIPTION
+
+Depending on what you want to work with there are different ways to
+approach Lintian and its code.
+
+=over 4
+
+=item * L<Writing a Lintian check|Lintian::Tutorial::WritingChecks>
+
+=item * L<Running (parts of) the Lintian test suite|Lintian::Tutorial::TestSuite>
+
+=item * L<Writing new Lintian tests|Lintian::Tutorial::WritingTests>
+
+=item * Understanding Lintian
+
+To be written.
+
+=back
+
+=begin :man
+
+=head1 SEE ALSO
+
+L<Lintian::Tutorial::WritingChecks>,
+L<Lintian::Tutorial::TestSuite>,
+L<Lintian::Tutorial::WritingTests>
+
+=end :man
+
+=cut
+
diff --git a/doc/tutorial/Lintian/Tutorial/TestSuite.pod b/doc/tutorial/Lintian/Tutorial/TestSuite.pod
new file mode 100644
index 0000000..3273388
--- /dev/null
+++ b/doc/tutorial/Lintian/Tutorial/TestSuite.pod
@@ -0,0 +1,115 @@
+=encoding utf-8
+
+=head1 NAME
+
+Lintian::Tutorial::TestSuite -- Quick intro to running the Lintian testsuite
+
+=head1 SYNOPSIS
+
+Warning: This document may be out of date.
+
+This guide will quickly introduce you to running the Lintian test
+suite and some tricks. The Lintian test suite is fairly large and
+accordingly it can take a substantial amount of time to run. To speed
+up development, there are various options to limit the tests to run.
+
+If you are looking for a guide on how to write tests, please consult
+L<Lintian::Tutorial::WritingTests>.
+
+=head1 DESCRIPTION
+
+The Lintian test suite is an extensive collection of various test
+cases. The test suite is divided into 4 "sub-suites". The majority
+of tests are currently located in the "tests" sub-suite.
+
+To run the full suite:
+
+ $ rm -rf debian/test-out; private/build-test-packages; private/runtests
+
+While writing a new tag (or check) you probably only want to run a
+particular (subset of the) test(s). See L</Running a subset of the
+tests> for the available options.
+
+=head2 Running a subset of the tests
+
+First, you have to build the test packages with:
+
+ $ rm -rf debian/test-out; private/build-test-packages;
+
+Then, the following options are available:
+
+=over 4
+
+=item Running a single test
+
+To run a single test by its name, use:
+
+ $ private/runtests --onlyrun=test:$name
+
+=item Running all tests for a check
+
+To run all tests for a given check, use:
+
+ $ private/runtests --onlyrun=check:$name
+
+$check must be the name of a check (it will test for
+checks/$check.desc) or "legacy". This will run all tests that start
+with "$check-".
+
+=item Running all tests designed for a specific tag
+
+To run all tests that have a "Test-For" or a "Test-Against" for a given
+tag, use:
+
+ $ private/runtests --onlyrun=tag:$name
+
+=back
+
+=head2 Running tests under coverage
+
+This feature is currently untested.
+
+It is possible to run most of the tests under L<Devel::Cover>. This is
+done by passing I<--coverage> to I<private/runtests>. Example:
+
+ $ private/runtests --coverage --dump-logs -j1 -k t debian/test-out
+
+Please note that L<Devel::Cover> does not seem to handle multiple
+threads too well. You may see spurious warnings/errors if you run the
+tests with 2 or more active worker threads.
+
+B<Caveat> 1: Coverage for collections (i.e. programs in I<collection/>)
+does not seem to work at the moment. Therefore, they often end up with
+(next to) zero coverage in the generated reports.
+
+B<Caveat> 2: L<Devel::Cover> sometimes changes the output of Lintian
+or tools called by Lintian. Obviously, this leads to test
+failures. Therefore, you may see weird test failures (or warnings)
+when running under coverage.
+
+=head3 Collecting the coverage you want in a reasonable time
+
+Collecting coverage is excruciatingly slow. This is not helped by the
+fact that it becomes unreliable when run under 2 or more threads.
+
+Fortunately, L<Devel::Cover> "appends" to its cover database. This
+allows you to "slowly" build up the coverage database over multiple
+runs. Example:
+
+ $ private/runtests --coverage --dump-logs -j1 -k t debian/test-out suite:scripts
+ $ private/runtests --coverage --dump-logs -j1 -k t debian/test-out suite:debs
+ $ private/runtests --coverage --dump-logs -j1 -k t debian/test-out suite:source
+ ...
+
+Or:
+
+ $ private/runtests --coverage --dump-logs -j1 -k t debian/test-out $check
+ $ private/runtests --coverage --dump-logs -j1 -k t debian/test-out legacy
+
+
+=head1 SEE ALSO
+
+L<Lintian::Tutorial::WritingTests>
+
+=cut
+
diff --git a/doc/tutorial/Lintian/Tutorial/WritingChecks.pod b/doc/tutorial/Lintian/Tutorial/WritingChecks.pod
new file mode 100644
index 0000000..b6642e1
--- /dev/null
+++ b/doc/tutorial/Lintian/Tutorial/WritingChecks.pod
@@ -0,0 +1,442 @@
+=encoding utf-8
+
+=head1 NAME
+
+Lintian::Tutorial::WritingChecks -- Writing checks for Lintian
+
+=head1 SYNOPSIS
+
+Warning: This tutorial may be outdated.
+
+This guide will quickly guide you through the basics of writing a
+Lintian check. Most of the work is in writing the two files:
+
+ checks/<my-check>.pm
+ checks/<my-check>.desc
+
+And then either adding a Lintian profile or extending an existing
+one.
+
+=head1 DESCRIPTION
+
+The basics of writing a check are outlined in the Lintian User Manual
+(§3.3). This tutorial will focus on the act of writing the actual
+check. In this tutorial, we will assume the name of the check to be
+written is "deb/pkg-check".
+
+The tutorial will work with a "binary" and "udeb" check. Checking
+source packages works in a similar fashion.
+
+=head2 Create a check I<.desc> file
+
+As mentioned, this tutorial will focus on the writing of a check.
+Please see the Lintian User Manual (§3.3) for how to do this part.
+
+=head2 Create the Perl check module
+
+Start with the template:
+
+ # deb/pkg-check is loaded as Lintian::deb::pkg_check
+ # - See Lintian User Manual §3.3 for more info
+ package Lintian::deb::pkg_check;
+
+ use strict;
+ use warnings;
+
+ sub run {
+ my ($pkg, $type, $info, $proc, $group) = @_;
+ return;
+ }
+
+The snippet above is a simple valid check that does "nothing at all".
+We will extend it in just a moment, but first let us have a look at
+the arguments at the setup.
+
+The I<run> sub is the entry point of our "deb/pkg-check" check; it
+will be invoked once per package it should process. In our case, that
+will be once per "binary" (.deb) and once per udeb package processed.
+
+It is given 5 arguments (in the future, possibly more), which are:
+
+=over 4
+
+=item $pkg - The name of the package being processed.
+
+(Same as $proc->pkg_name)
+
+=item $type - The type of the package being processed.
+
+At the moment, $type is one of "binary" (.deb), "udeb", "source"
+(.dsc) or "changes". This argument is mostly useful if certain checks
+do not apply equally to all package types being processed.
+
+Generally it is advisable to check only binaries ("binary" and
+"udeb"), sources or changes in a given check. But in rare cases, it
+makes sense to lump multiple types together in the same check and this
+argument helps you do that.
+
+(Current it is always identical to $proc->pkg_type)
+
+=item $info - Accessor to the data Lintian has extracted
+
+Basically all information you want about a given package comes from
+the $info object. Sometimes referred to as either the "info object" or
+(an instance of) L<Lintian::Collect>.
+
+This object (together with a properly set Needs-Info in the I<.desc>
+file) will grant you access to all of the data Lintian has extracted
+about this package.
+
+Based on the value of the $type argument, it will be one of
+L<Lintian::Collect::Binary>, L<Lintian::Collect::Changes> or
+L<Lintian::Collect::Source>.
+
+(Currently it is the same as $proc->info)
+
+=item $proc - Basic metadata about the package
+
+This is an instance of L<Lintian::Processable> and is useful for
+trivially obtaining very basic package metadata. Particularly, the
+name of source package and version of source package are readily
+available through this object.
+
+=item $group - Group of processables from the same source
+
+If you want to do a cross-check between different packages built from
+the same source, $group helps you access those other packages
+(if they are available).
+
+This is an instance of L<Lintian::ProcessableGroup>.
+
+=back
+
+Now back to the coding.
+
+=head2 Accessing fields
+
+Let's do a slightly harder example. Assume we wanted to emit a tag for
+all packages without a (valid) Multi-Arch field. This requires us to
+A) identify if the package has a Multi-Arch field and B) identify if
+the content of the field was valid.
+
+Starting from the top. All $info objects have a method called field,
+which gives you access to a (raw) field from the control file of the
+package. It returns C<undef> if said field is not present or the
+content of said field otherwise. Note that field names must be given
+in all lowercase letters (i.e. use "multi-arch", not "Multi-Arch").
+
+This was the first half. Let's look at checking the value. Multi-arch
+fields can (currently) be one of "no", "same", "foreign" or "allowed".
+One way of checking this would be using the regex:
+
+Notice that Lintian automatically strips leading and trailing spaces
+on the I<first> line in a field. It also strips trailing spaces from
+all other lines, but leading spaces and the " ."-continuation markers
+are kept as is.
+
+=head2 Checking dependencies
+
+Lintian can do some checking of dependencies. For most cases it works
+similar to a normal dependency check, but keep in mind that Lintian
+uses I<pure> logic to determine if dependencies are satisfied (i.e. it
+will not look up relations like Provides for you).
+
+Suppose you wanted all packages with a multi-arch "same" field to
+pre-depend on the package "multiarch-support". Well, we could use the
+L<< $info->relation|Lintian::Collect::Binary/relation (FIELD) >> method for
+this.
+
+$info->relation returns an instance of L<Lintian::Relation>. This
+object has an "implies" method that can be used to check if a package
+has an explicit dependency. Note that "implies" actually checks if
+one relation "implies" another (i.e. if you satisfied relationA then
+you definitely also satisfied relationB).
+
+As with the "field"-method, field names have to be given in all
+lowercase. However "relation" will never return C<undef> (not even if the
+field is missing).
+
+=head2 Using static data files
+
+Currently our check mixes data and code. Namely all the valid values
+for the Multi-Arch field are currently hard-coded in our check. We can
+move those out of the check by using a data file.
+
+Lintian natively supports data files that are either "sets" or
+"tables" via L<Lintian::Data> (i.e. "unordered" collections). As an
+added bonus, L<Lintian::Data> transparently supports vendor specific
+data files for us.
+
+First we need to make a data file containing the values. Which could be:
+
+ # A table of all the valid values for the multi-arch field.
+ no
+ same
+ foreign
+ allowed
+
+This can then be stored in the data directory as
+I<data/deb/pkg-check/multiarch-values>.
+
+Now we can load it by using:
+
+ use Lintian::Data;
+
+ my $VALID_MULTI_ARCH_VALUES =
+ Lintian::Data->new('deb/pkg-check/multiarch-values');
+
+Actually, this is not quite true. L<Lintian::Data> is lazy, so it
+will not load anything before we force it to do so. Most of the time
+this is just an added bonus. However, if you ever have to force it to
+load something immediately, you can do so by invoking its "known"
+method (with an arbitrary defined string and ignore the result).
+
+Data files work with 3 access methods, "all", "known" and "value".
+
+=over 4
+
+=item all
+
+"all" (i.e. $data->all) returns a list of all the entries in the data
+file (for key/value tables, all returns the keys). The list is not
+sorted in any order (not even input order).
+
+=item known
+
+"known" (i.e. $data->known('item')) returns a truth value if a given
+item or key is known (present) in the data set or table. For key/pair
+tables, the value associated with the key can be retrieved with
+"value" (see below).
+
+=item value
+
+"value" (i.e. $data->value('key')) returns a value associated with a
+key for key/value tables. For unknown keys, it returns C<undef>. If
+the data file is not a key/value table but just a set, value returns
+a truth value for known keys.
+
+=back
+
+While we could use both "value" and "known", we will use the latter
+for readability (and to remind ourselves that this is a data set and
+not a data table).
+
+Basically we will be replacing:
+
+ unless exists $VALID_MULTI_ARCH_VALUES{$multiarch};
+
+with
+
+ unless $VALID_MULTI_ARCH_VALUES->known($multiarch);
+
+=head2 Accessing contents of the package
+
+Another heavily used mechanism is to check for the presence (or absence)
+of a given file. Generally this is what the
+L<< $info->index|Lintian::Collect::Package/index (FILE) >> and
+L<< $info->sorted_index|Lintian::Collect::Package/sorted_index >> methods
+are for. The "index" method returns instances of L<Lintian::Path>,
+which has a number of utility methods.
+
+If you want to loop over all files in a package, the sorted_index will
+do this for you. If you are looking for a specific file (or directory), a
+call to "index" will be much faster. For the contents of a specific directory,
+you can use something like:
+
+ if (my $dir = $info->index('path/to/dir/')) {
+ foreach my $elem ($dir->children) {
+ print $elem->name . " is a file" if $elem->is_file;
+ # ...
+ }
+ }
+
+Keep in mind that using the "index" or "sorted_index" method will
+require that you put "unpacked" in Needs-Info. See L</Keeping Needs-Info
+up to date>.
+
+There are also a pair of methods for accessing the control files of a
+binary package. These are
+L<< $info->control_index|Lintian::Collect::Package/control_index (FILE) >> and
+L<< $info->sorted_control_index|Lintian::Collect::Package/sorted_control_index >>.
+
+=head3 Accessing contents of a file in a package
+
+When you actually want to see the contents of a file, you can use
+L<open|Lintian::Path/open> (or L<open_gz|Lintian::Path/open_gz>) on
+an object returned by e.g.
+L<< $info->index|Lintian::Collect::Package/index (FILE) >>. These
+methods will open the underlying file for reading (the latter
+applying a gzip decompression).
+
+However, please do assert that the file is safe to read by calling
+L<is_open_ok|Lintian::Path/is_open_ok> first. Generally, it will
+only be true for files or safely resolvable symlinks pointing to
+files. Should you attempt to open a path that does not satisfy
+those criteria, L<Lintian::Path> will raise a trappable error at
+runtime.
+
+Alternatively, if you access the underlying file object, you can
+use the L<fs_path|Lintian::Path/fs_path> method. Usually, you will
+want to test either L<is_open_ok|Lintian::Path/is_open_ok> or
+L<is_valid_path|Lintian::Path/is_valid_path> first to ensure you do
+not follow unsafe symlinks. The "is_open_ok" check will also assert
+that it is not (e.g.) a named pipe or such.
+
+Should you call L<fs_path|Lintian::Path/fs_path> on a symlink that
+escapes the package root, the method will throw a trappable error at
+runtime. Once the path is returned, there are no more built-in
+fail-safes. When you use the returned path, keep things like
+"../../../../../etc/passwd"-symlink and "fifo" pipes in mind.
+
+
+In some cases, you may even need to access the file system objects
+I<without> using L<Lintian::Path>. This is, of course, discouraged
+and suffers from the same issues above (all checking must be done
+manually by you). Here you have to use the "unpacked", "debfiles" or
+"control" methods from L<Lintian::Collect> or its subclasses.
+
+
+
+The following snippet may be useful for testing that a given path does
+not escape the root.
+
+ use Lintian::Util qw(is_ancestor_of);
+
+ my $path = ...;
+ # The snippet applies equally well to $info->debfiles and
+ # $info->control (just remember to subst all occurrences of
+ # $info->unpacked).
+ my $unpacked_file = $info->unpacked($path);
+ if ( -f $unpacked_file && is_ancestor_of($info->unpacked, $unpacked_file)) {
+ # a file and contained within the package root.
+ } else {
+ # not a file or an unsafe path
+ }
+
+=head2 Keeping Needs-Info up to date
+
+Keeping the "Needs-Info" field of your I<.desc> file is a bit of
+manual work. In the API description for the method there will
+generally be a line looking something like:
+
+ Needs-Info requirements for using methodx: Y
+
+Which means that the methodx requires Y to work. Here Y is a comma
+separated list and each element of Y basically falls into 3 cases.
+
+=over 4
+
+=item * The element is the word I<none>
+
+In this case, the method has no "external" requirements and can be
+used without any changes to your Needs-Info. The "field" method
+is an example of this.
+
+This only makes sense if it is the only element in the list.
+
+=item * The element is a link to a method
+
+In this case, the method uses another method to do its job. An example
+is the
+L<sorted_control_index|Lintian::Collect::Binary/sorted_control_index>
+method, which uses the
+L<control_index|Lintian::Collect::Binary/control_index (FILE)>
+method. So using I<sorted_control_index> has the same requirements as
+using I<control_index>.
+
+=item * The element is the name of a collection (e.g. "control_index").
+
+In this case, the method needs the given collection to be run. So to
+use (e.g.) L<control_index|Lintian::Collect::Binary/control_index (FILE)>,
+you have to put "bin-pkg-control" in your Needs-Info.
+
+=back
+
+CAVEAT: Methods can have different requirements based on the type of
+package! An example of this "changelog", which requires "changelog-file"
+in binary packages and "Same as debfiles" in source packages.
+
+=head2 Avoiding security issues
+
+Over the years a couple of security issues have been discovered in
+Lintian. The problem is that people can in theory create some really nasty
+packages. Please keep the following in mind when writing a check:
+
+=over 4
+
+=item * Avoid 2-arg open, system/exec($shellcmd), `$shellcmd` like the
+plague.
+
+When you get any one of those wrong you introduce "arbitrary code
+execution" vulnerabilities (we learned this the hard way via
+CVE-2009-4014).
+
+Usually 3-arg open and the non-shell variant of system/exec are
+enough. When you actually need a shell pipeline, consider using
+L<Lintian::Command>. It also provides a I<safe_qx> command to assist
+with capturing stdout as an alternative to `$cmd` (or qx/$cmd/).
+
+=item * Do not trust field values.
+
+This is especially true if you intend to use the value as part of a
+file name. Verify that the field contains what you expect before you use
+it.
+
+=item * Use L<Lintian::Path> (or, failing that, is_ancestor_of)
+
+You might be tempted to think that the following code is safe:
+
+ use autodie;
+
+ my $filename = 'some/file';
+ my $ufile = $info->unpacked($filename);
+ if ( ! -l $ufile) {
+ # Looks safe, but isn't in general
+ open(my $fd, '<', $ufile);
+ ...;
+ }
+
+This is definitely unsafe if "$filename" contains at least one
+directory segment. So, if in doubt, use
+L<is_ancestor_of|Lintian::Util/is_ancestor_of(PARENTDIR, PATH)> to
+verify that the requested file is indeed the file you think it is. A
+better version of the above would be:
+
+ use autodie,
+ use Lintian::Util qw(is_ancestor_of);
+ [...]
+ my $filename = 'some/file';
+ my $ufile = $info->unpacked($filename);
+ if ( ! -l $ufile && -f $ufile && is_ancestor_of($info->unpacked, $ufile)) {
+ # $ufile is a file and it is contained within the package root.
+ open(m $fd, '<', $ufile);
+ ...;
+ }
+
+In some cases you can even drop the "! -l $ufile" part.
+
+Of course, it is much easier to use the L<Lintian::Path> object
+(whenever possible).
+
+ my $filename = 'some/file';
+ my $ufile = $info->index($filename);
+ if ( $ufile && $ufile->is_file && $ufile->is_open_ok) {
+ my $fd = $ufile->open;
+ ...;
+ }
+
+Here you can drop the " && $ufile->is_file" if you want to permit
+safe symlinks.
+
+
+For more information on the is_ancestor_of check, see
+L<is_ancestor_of|Lintian::Util/is_ancestor_of(PARENTDIR, PATH)>
+
+
+=back
+
+=head1 SEE ALSO
+
+L<Lintian::Tutorial::WritingTests>, L<Lintian::Tutorial::TestSuite>
+
+=cut
diff --git a/doc/tutorial/Lintian/Tutorial/WritingTests.pod b/doc/tutorial/Lintian/Tutorial/WritingTests.pod
new file mode 100644
index 0000000..1011235
--- /dev/null
+++ b/doc/tutorial/Lintian/Tutorial/WritingTests.pod
@@ -0,0 +1,539 @@
+=encoding utf-8
+
+=head1 NAME
+
+Lintian::Tutorial::WritingTests -- Short tutorial on writing tests
+
+=head1 SYNOPSIS
+
+Warning: This document may be out of date.
+
+This document attempts to be a short / quick tutorial to the Lintian
+test suite from a test-writer's perspective. As such, it will only
+cover the standard type of tests (from the "tests" suite).
+
+The guide will involve writing a test for the "deb/pkg-check" check,
+which was documented in the L<Lintian::Tutorial::WritingChecks>
+tutorial.
+
+For running tests, please see L<Lintian::Tutorial::TestSuite> instead.
+
+=head1 DESCRIPTION
+
+The Lintian test suite is divided into several parts. These are:
+
+=over 4
+
+=item -
+
+scripts
+
+Small (Perl) "prove" tests. These assert that code style, data files
+and/or self-contained code units (i.e. unit tests) work as intended.
+They are B<not> used for testing Lintian tags.
+
+=item -
+
+tags
+
+These tests all test for the presence of tags after building test
+packages using skeletons. For most cases, we recommend
+
+ Skeleton: upload-non-native
+
+suites are small test suites that test some particular tags for
+I<.changes>, I<.deb> or I<.dsc> files. Typically, you will find the
+more exotic tags here, which require some special fiddling and cannot
+be built by a "standard" dh7 + dpkg build.
+
+=item -
+
+literal
+
+These tests look to match the literal output of Lintian. These tests
+are useful as general false positives. They also catch Lintian messages
+unrelated to tags.
+
+=back
+
+With this in mind, let us move on to the scope.
+
+=head2 Scope of the tutorial
+
+WARNING: THE REMAINDER OF THIS TUTORIAL IS OUT OF DATE.
+
+The "tests" suite alone is fairly complex on its own. To keep things
+simple, the tutorial will limit itself to creating a "native"
+package with no special requirements in the "tests" suite.
+
+In particular, note that the tags I<must not> be I<pedantic> for this
+to work. If you followed the check writing tutorial and made the tags
+pedantic, please change them into "I", "W" or "E" tags.
+
+Once the basics are covered, you should be better equipped to deal
+with the other ("tag testing") suites or using other features of the
+"tests" suite (e.g. pedantic tags).
+
+=head2 The design of the Lintian test suite
+
+The basic design of the Lintian test suite can be summed up
+as I<less is more>. The Debian build system is changing all the time
+(albeit, slowly) and sometimes it deprecates or breaks existing
+features.
+
+With over 400 tests all featuring the same basic parts, the test suite
+features several tricks to keep up with the pace. It uses "skeletons"
+(template) directories to seed the package structures and template
+files to fill in the basic files (e.g. "debian/control" and
+"debian/changelog").
+
+This means that when a new standards-version comes along, debhelper
+deprecates a feature or (more likely) Lintian adds a new tag, the
+majority of the tests can quickly be adapted with only a minor effort.
+
+Since pedantic tags tend to require additional effort to avoid, most
+Lintian tests do B<not> run with pedantic tags enabled.
+
+=head2 The basics of a "native" package in the "tests" suite
+
+For starters, you need 2 files and 1 directory, which will be placed
+in I<< t/tests/<test-name> >>.
+
+=head3 The desc file (mandatory)
+
+This is the test description file. It is a deb822 file (i.e. same
+syntax as I<debian/control>), which contains a number of fields.
+
+Let's start with the following template:
+
+ Testname: pkg-deb-check-general
+ Version: 1.0
+ Description: General test of the pkg/deb-check check
+ Test-For:
+ missing-multi-arch-field
+ missing-pre-depends-on-multiarch-support
+
+This defines the name of the test, its sequence number (i.e. how early
+it should be run), the version of the I<generated> package, a
+description and the tags you intend to test for.
+
+In case you were wondering why "invalid-multi-arch-field" is not
+listed, then it is because dpkg will not allow us to use an invalid
+Multi-Arch value. Therefore, that particular tag would have to be
+tested in the "debs" suite instead.
+
+Note that the value of the Testname field (as Source field), Version
+field and Description field (as the synopsis) I<will> be used in the
+package. As such, they must obey the normal requirements for these
+purposes.
+
+Please keep the following conventions in mind:
+
+=over 4
+
+=item -
+
+The Testname should be "<check-name>-<test-name>"
+
+Note that regular Lintian checks do I<not> have a "/", so the naming
+convention works slightly better there.
+
+=item -
+
+The Version should always be "1.0" unless the test requires anything else.
+
+For non-native packages, the default would be "1.0-1".
+
+=back
+
+=head3 The "tags" file (mandatory, but may be empty)
+
+This file contains the I<sorted> "expected" output of lintian.
+Assuming all of the tags are "I" tags, the file should look something
+like:
+
+ I: pkg-deb-check-general-missing-ma: missing-multi-arch-field
+ I: pkg-deb-check-general-missing-pred: missing-pre-depends-on-multiarch-support
+
+=head3 The "debian/" directory (optional, but usually needed)
+
+The unpacked debian package in its full glory. Note that this means
+that the (e.g.) I<debian/rules> file would be I<<
+t/tests/<test-name>/debian/debian/rules >> (note the double
+"debian/").
+
+The directory is seeded from I<< t/templates/tests/<skeleton>/ >>,
+where I<skeleton> is the value of the "Skeleton" field from the "desc"
+file.
+
+For this test, you only need a specialized control file. This file
+could look something like:
+
+ Source: {$source}
+ Priority: extra
+ Section: {$section}
+ Maintainer: {$author}
+ Standards-Version: {$standards_version}
+ Build-Depends: {$build_depends}
+
+ Package: {$source}-missing-ma
+ Architecture: {$architecture}
+ Depends: $\{shlibs:Depends\}, $\{misc:Depends\}
+ Description: {$description} (invalid)
+ This is a test package designed to exercise some feature or tag of
+ Lintian. It is part of the Lintian test suite and may do very odd
+ things. It should not be installed like a regular package. It may
+ be an empty package.
+ .
+ Missing M-A field.
+
+ Package: {$source}-missing-pred
+ Architecture: any
+ Depends: $\{shlibs:Depends\}, $\{misc:Depends\}
+ Multi-arch: same
+ Description: {$description} (pre-depends)
+ This is a test package designed to exercise some feature or tag of
+ Lintian. It is part of the Lintian test suite and may do very odd
+ things. It should not be installed like a regular package. It may
+ be an empty package.
+ .
+ Missing Pre-Depends.
+
+=head3 Running the test
+
+At this point, the test is in fact ready to be executed. It can be
+run by using:
+
+ $ debian/rules runtests onlyrun=pkg-deb-check-general
+
+ OR
+
+ $ private/runtests --dump-logs t debian/test-out pkg-deb-check-general
+
+However, it will not emit the correct tags unless pkg/deb-check is
+part of the debian/main lintian profile. If your check is a part of a
+different profile, add the "Profile: <name>" field to the "desc" file.
+
+With this, the tutorial is over. Below you will find some more
+resources that may be useful to your future test writing work.
+
+=head1 REFERENCES / APPENDIX
+
+=head2 A step-by-step guide of how a test case works
+
+Basically, the tag-testing test cases all involve building a package
+and running lintian on the result. The "tests" suite does a full
+build with dpkg-buildpackage, the other suites "hand-craft" only the
+type of artifacts they are named after (e.g. "source" produces only
+source packages).
+
+=head3 A test in the "tests" suite
+
+The basic process of a lintian test in the "tests" suite.
+
+=over 4
+
+=item 1
+
+Copy the "upstream" skeleton dir into the build dir (non-native only)
+
+=item 2
+
+Copy the "upstream" dir from the test into the build dir (if present, non-native only)
+
+=item 3
+
+Run the "pre_upstream" hook (if present, non-native only)
+
+=item 4
+
+Assemble the upstream tarball (non-native only)
+
+=item 5
+
+Copy the "debian" skeleton dir into the build dir
+
+=item 6
+
+Copy the "debian" directory from the test into the build dir (if present)
+
+=item 7
+
+Create debian/control and debian/changelog from "I<< <file> >>.in" if
+they do not exist.
+
+=item 8
+
+Create an empty watch file (if missing, non-native only)
+
+=item 9
+
+Run the "pre_build" hook (if present)
+
+=item 10
+
+Run dpkg-buildpackage
+
+=item 11
+
+Run lintian on the build result
+
+=item 12
+
+Run the "post_test" hook (if present)
+
+=item 13
+
+Run the "test_calibration" hook (if present), which may produce
+a new "expected output file".
+
+=item 14
+
+Compare the result with the expected output.
+
+=back
+
+Note that the majority of the steps are conditional on
+native/non-native packages or presence of hooks.
+
+=head3 A test in the "debs" and the "source" suite
+
+The "debs" and the "source" suite share the same basic steps, which
+are:
+
+=over 4
+
+=item 1
+
+Copy the skeleton dir into the build dir
+
+=item 2
+
+Copy the test directory files into the build dir
+
+=item 3
+
+Create changelog, control, and (debs-only) Makefile from "I<< <file>
+>>.in" if they do not exist.
+
+=item 4
+
+Run make in the build dir
+
+=item 5
+
+Run lintian on the produced artifact (there must be exactly one)
+
+=item 6
+
+Compare the result with the expected output.
+
+=back
+
+=head3 A test in the "changes" suite
+
+The changes test is fairly simple as there is not much building. The
+steps are as the following:
+
+=over 4
+
+=item 1
+
+Find or compute the test artifact as the following:
+
+=over 4
+
+=item -
+
+If I<< <test-dir>/<test-name>.changes >> exists, it is used as the
+artifact.
+
+=item -
+
+Otherwise, copy I<< <test-dir>/<test-name>.changes.in >> into the build dir
+and use it as a template to create I<< <build-dir>/<test-name>.changes
+>>. The result is then used as the artifact to test.
+
+=back
+
+=item 2
+
+Run lintian run on the artifact
+
+=item 3
+
+Compare the result with the expected output
+
+=back
+
+=head2 The full layout of a test in the "tests" suite
+
+Each test in the "tests" suite is placed in
+I<< t/tests/<check>-<name> >>. In these you will find some
+of the following files:
+
+=over 4
+
+=item -
+
+desc (mandatory)
+
+This is the test description file. It is a deb822 file (i.e. same
+syntax as I<debian/control>), which contains a number of fields.
+
+=item -
+
+tags (mandatory, but may be empty)
+
+This file contains the "expected" output of lintian.
+
+This is generally sorted, though a few tests rely on the order of
+the output. This can be controlled via the "Sort" field in the "desc"
+file.
+
+=item -
+
+debian/ (optional, but usually what you need)
+
+The unpacked debian package. For "native" package tests, this is
+I<also> the "upstream" part. For "non-native" package tests, this can
+be used to override files in the "upstream" part (rarely needed).
+
+The actual packaging files (e.g. I<debian/rules>) would be in
+
+ I<< t/tests/<test-name>/debian/debian/rules >>
+
+Note the double "debian".
+
+This part is seeded from I<< t/templates/tests/<skeleton>/ >>,
+where I<skeleton> is the value of the "Skeleton" field from the "desc"
+file.
+
+=item -
+
+upstream/ (optional, rarely needed)
+
+This directory is the used to create the "upstream" tarball for
+"non-native" package tests. Since most tags are emitted for both
+"native" and "non-native" tests, it is simpler (and slightly faster)
+to use "native" packages for most tests.
+
+The files here should also be present with the same contents in the
+debian directory unless you're intentionally creating a diff.
+However, as normal with a Debian package, you can omit files entirely
+from the debian directory and the deletions will be ignored by
+dpkg-buildpackage.
+
+The directory will be seeded from I<<
+t/templates/tests/<skeleton>.upstream/ >>, where I<skeleton> is the
+value of the "Skeleton" field from the "desc" file.
+
+=item -
+
+post_test (optional, rarely needed)
+
+This script (if present) is a sed script that can be used to "massage"
+the output of lintian before comparing it with the "expected output".
+
+The most common use for this script is to remove the architecture
+name, multi-arch path, drop hardening tags or exact standards-version
+number from tags output. Here are some examples files used:
+
+ # Remove the exact standards version, so the tags file will not need
+ # to be updated with every new standards-version
+ s/\(current is ([0-9]+\.)+[0-9]\)/(current is CURRENT)/
+
+ # Drop all hardening tags (they can differ between architectures)
+ /: hardening-.*/ d
+
+ # Massage e.g. usr/lib/i386-linux-gnu/pkgconfig into a generic path
+ s, usr/lib/[^/]+/pkgconfig/, usr/lib/ARCH/pkgconfig/,
+
+It may be useful for other cases where the output of Lintian may
+change on different systems.
+
+=item -
+
+pre_build / pre_upstream (optional, special case usage)
+
+If present and executable, these scripts can be used to mess with the
+package directory and (what will become) the upstream tarball.
+
+Their common use case is to create files in the tarballs that cannot
+(or preferably should not) be included in the revision control system.
+Common cases include "binary", "minimized" files or files with "weird"
+names such as backslashes or non UTF-8 characters.
+
+Both scripts receive a directory as first argument, which is the
+directory they should work on. For:
+
+=over 4
+
+=item -
+
+pre_upstream
+
+The script will be run before the upstream tarball is compiled. The
+first argument is the directory that will be included in the upstream
+tarball.
+
+=item -
+
+pre_build
+
+The script will be run before dpkg-buildpackage is invoked. The first
+argument is the directory of the unpacked debian source package.
+
+=back
+
+=item -
+
+test_calibration (optional, special case usage)
+
+If present and executable, this script will be invoked B<after>
+lintian I<and> post_test (if present) have been run. The script can
+then modify the expected output I<and> the actual output.
+
+This is useful for those extremely rare cases where post_test is
+insufficient to handle the requirements. So far, this has only been
+needed for the hardening checks, where the output differs between
+architectures.
+
+The script will be passed 3 arguments:
+
+=over 4
+
+=item -
+
+Path to the "expected output" file (read-only)
+
+This is the "tags" file from the test suite and B<must not> be
+modified.
+
+=item -
+
+Path to the "actual output" file (read-write)
+
+This is the file as lintian and post_test created it.
+
+=item -
+
+Path to the "calibrated expected output" (create+write)
+
+This file does not exist and should be created by the script, if it
+wishes to change the "expected output". If this file exists when the
+script terminates, this file will be used instead of the original
+"expected output" file.
+
+=back
+
+=back
+
+=head1 SEE ALSO
+
+The READMEs in the suites: I<t/tests/README>, I<t/changes/README>,
+I<t/debs/README> and I<t/source/README>.
+
+L<Lintian::Tutorial::WritingChecks>, L<Lintian::Tutorial::TestSuite>
+
+=cut