diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/CREDITS | 67 | ||||
-rw-r--r-- | doc/README.developers.pod | 189 | ||||
-rw-r--r-- | doc/examples/checks/my-vendor/another-check.desc | 7 | ||||
-rw-r--r-- | doc/examples/checks/my-vendor/some-check.desc | 6 | ||||
-rw-r--r-- | doc/examples/lintianrc | 56 | ||||
-rw-r--r-- | doc/examples/profiles/my-vendor/main.profile | 18 | ||||
-rw-r--r-- | doc/examples/tags/m/missing-build-depends-on-my-vendor-tools.desc | 5 | ||||
-rw-r--r-- | doc/examples/tags/m/missing-some-important-file.desc | 5 | ||||
-rw-r--r-- | doc/lintian.rst | 992 | ||||
-rw-r--r-- | doc/releases.md | 137 | ||||
-rw-r--r-- | doc/tutorial/Lintian/Tutorial.pod | 39 | ||||
-rw-r--r-- | doc/tutorial/Lintian/Tutorial/TestSuite.pod | 115 | ||||
-rw-r--r-- | doc/tutorial/Lintian/Tutorial/WritingChecks.pod | 442 | ||||
-rw-r--r-- | doc/tutorial/Lintian/Tutorial/WritingTests.pod | 539 |
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 &, < and > + (respectively). Please also escape _ as _ and * as *. + + 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 |