# -*- perl -*-
#
# Use "perldoc doc/README.developers" to read it like a manpage.

=head1 NAME

README.developers -- 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
pages lintian(1) and lintian-info(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 "frontend". This directory holds the "lintian" executable.
This is what gets called when a user calls lintian. The 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 frontend

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 frontend/

=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 testset

the legacy 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 Emit (Tag)

Tag that was not supressed 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.  It comes in two variants, static or
temporary.

Temporary laboratories (as the name suggests) expire as soon as
Lintian is done with its tasks.

Static laboratories are generally used on lintian.d.o(-like) setups,
where packages remain in a (semi-)unpacked state after processing.

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.

=back

=head2 Useful tricks

There is an extended description of tricks on
L<http://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.  The following
shell snippet can be used for this purpose:

 #!/bin/sh
 LINTIAN_ROOT="<INSERT PATH TO LINTIAN GIT DIR>"
 export LINTIAN_ROOT
 exec "$LINTIAN_ROOT/frontend/lintian" "$@"

Beware of two things: If LINTIAN_ROOT is not set, Lintian 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.

=head3 Running tests

Lintian has two "major" test-suites; the first one is the "new" test
suite, which is devided into 5 sub-suites, and then there is the
"legacy" test suite.  Running all of the tests is as simple as
invoking:

 $ debian/rules runtests

Lintian has a large test suite that easily takes up to 30 minutes.  So
when debugging a particular test or check, you may want to run only
parts of the test suite.

Unless otherwise stated, only the new test suite supports the "extra"
run options listed below.  The legacy test-suite will generally give a
warning about it being unable to find a test to run.

=over 4

=item Changing parallelization

The test suite respects the "DEB_BUILD_OPTIONS=parallel=n", though "n"
denotes the amount of "worker" threads.  The test runner will
generally have 2 threads more than that.  Also each "worker" will run
lintian, which parallelizes its unpacking as well.

In case you are wondering about the 2 extra threads in the test
runner, the first of them is the "coordinator"-thread (which will
generally be waiting when the workers are active) and the second one
is the "output"-thread (which handles the fancy output).

Note: the legacy test suite only runs a single test at a time regardless
of this setting.

=item Running a single test

To run a single test by its name, use:

 $ debian/rules runtests onlyrun=$name

The legacy test suite supports this.

Note: if the name does not match any test you will see up to two
warnings about the test could not be found.  If the test only exists
in one of the suites (which is usually the case), you will see a
warning from the other suite.

=item Running all tests for a check

To run all tests for a given check, use:

 $ debian/rules runtests onlyrun=$check

$check must be the name of a check (it will test for
checks/$check.desc).  This will run all tests that starts with
"$check-".

Note: The "changes" sub-suite in the new test suite does not support
this.

If the name of the check clashes with the name of a test in the legacy
test suite, then that test will also be run.  Otherwise a warning will
be printed from the legacy test suite.

=item Running all tests in a sub-suite

To run all tests in a given sub-suite, use:

 $ debian/rules runtests onlyrun=suite:$suites

$suites is a comma-separated list of names of sub-suites to run.

Note: this cannot be used to influence the order, in which the sub-suites
are run.

=item Running all tests designed for a specific tag

To run all tests that has a "Test-For" or a "Test-Against" for a given
tag, use:

 $ debian/rules check-tag tag=$tag

The legacy test suite will not be run in this case.

=item Running only the legacy test suite

To run only the tests in legacy test suite use:

 $ debian/rules runtests onlyrun=--legacy-only

The new test suite will not be run in this case, but it is not possible
to select specific tests to run.

=back

=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.


An overview of how the collections and checks relate can be obtained
by I<private/graph>, which generates a "Graphviz Dot" graph of the
relations.

=cut

