Specification Synopsis
This specification aims to add vendor-based customization for Lintian.
The specification is based on the debate from Lintian BoF from DC10; the initial proposal is available here. Suggestions for changes to the specification or implementation should be sent to the Lintian Team.
Note the implementation has been merged into master branch.
Requirements
These are the requirements for the implementation of this specification.
- No code changes:
- It must be possible to alter whether Lintian emits a tag without modifying code.
- Re-usable:
- Most profiles will likely be based on the core profile. New profiles should be able to "extend" existing profile.
- Extended profile must be able to include tags not originally in the original profile.
- Extended profile must be able to exclude tags originally in the original profile.
- Add vendor/3rd party checks [Deferred]:
- A profile may include new checks/collections not present in the Lintian package itself.
- A tag not included in the current profile shall not be emitted.
- An override for such a tag is not considered "unneeded" and must be ignored.
The "Add vendor/3rd party checks" requirement is deferred for now and the specification will later be extended to include it.
Extensions
- Allow profiles to mark tags as "cannot be overridden"/"not overridable".
- Support FTP-master auto-reject as a profile.
Implementation would effectively solve (536364)
- Allow profiles to alter severity (but not certainty).
- What is serious to us may be minor to others.
- The --display-level argument should operate in terms of active profile's severity and not original severity
- Allow current tag selection command arguments to affect the profile.
- suppress-tags{,-from-file} suppresses tags even if the current profile would have included them.
Proposed Solution
We add a new directory to the Lintian root called "profiles" with the structure:
profiles/ debian/ main.profile ftp-auto-reject.profile ubuntu/ main.profile $other_vendor/ some.profile
Profiles should be specified with a new command line argument --profile <profile> or the environment/lintianrc variable LINTIAN_PROFILE=<profile>.
Lintian will use dpkg-vendor (or Dpkg::Vendor) to determine the best possible default vendor if not explicitly given (as mentioned above). If Lintain cannot find a profile for the current vendor, it will try the parent until it runs out of options. In this case, Lintian shall fail.
<profile> should be specified as $VENDOR/$profile or $VENDOR. The latter being short for $VENDOR/main. The actual file name of the profile will be $VENDOR/$profile.profile and should be located in:
~/.lintian/profiles/ /etc/lintian/profiles/ $LINTIAN_ROOT/profiles/
All of these directories (if they exist) are expected to have the same layout (as described above). Profile names cannot contain ".".
Profile file format
The general format is the same as always (same as our desc files or debian/control) - see The Policy Manual for more info:
Profile: <name> Extends: <profile> Enable-Tags-From-Check: <check>[, <check2> ...] Disable-Tags-From-Check: <check>[, <check2> ...] Enable-Tags: <tag>[, <tag2> ...] Disable-Tags: <tag>[, <tag2> ...]
All fields are "folded", except for Profile and Extends, which are both "simple" fields. The semantics are:
Profile is required and contains the (machine-readable) name of the profile; this should be used in the output to identify the chosen profile.
Extends is optional and denotes the profile this profile is based on. Lintian will recursively process the extended profile before continuing with processing this profile. Said profile is located by traversing the profile directories (as listed above). In the absence of this field, the profile is not based on another profile.
A profile is considered invalid and is rejected if it (in)directly extends itself.
Enable-Tags-From-Check and Disable-Tags-From-Check are both optional. They respectively enable or disable all the tags within checks. The profile is invalid and is rejected, if it lists the same check twice - even if it is in the same field. However, it is valid to enable or disable a check that was (respectively) disabled or enabled by a profile extended by profile.
It is not an error to enable or disable a check that is already enabled or disabled (respectively).
Enable-Tag and Disable-Tag are both optional. They work analogous to Enable-Check and Disable-Check except they only affect a single tag. It is allowed to allowed to list a tag in Enable-Tag or Disable-Tag even if the check that provides this tag is listed in the Disable-Check or Enable-Check field. In case of conflict, Enable-Tag / Disable-Tag shall overrule Disable-Check / Enable-Check within the profile.
In the absence of the fields Extends, Enable-Tag, Disable-Tag, Enable-Check and Disable-Check, the profile shall simply include all checks/tags known to it.
Possible extensions to this would be to allow patterns in the *-Tag fields. A pattern from Disable-Tag overrules a pattern in Enable-Tag. A specific tag name always overrules a pattern.
Extra Sections
As described in the requirements, there are number of optional requirements that we can look at. I believe this can be addressed by extending the above profile format with an optional number of extra stanzas:
Tags: <tag>[, <tag2> ...] Overridable: <yes|no> Severity: <tag severity>
The Tags field is "folded", Severity and Overridable are "simple" fields.
Tags lists the field affected by this stanza. Overridable denotes whether or not the tags can be overridden. Severity sets the severity of the listed tags to a known Lintian severity.
Tag must be present in each of these stanzas. At least one of Overridable and Severity must be present.
Implementation
The implementation has started and is available from the vendor-profile branch in the Lintian git repository.
Please note that some Debian profiles are auto-generated. These can be generated/updated by running:
$ debian/rules profiles
It generates a profile based on all the checks in checks/ - If you add a new check file, you will need to re-run said target - but it is not needed if you just add a new tag to an existing check.
Changelog
Merged into the master branch.
- Renamed some fields ending with Tag to use Tags instead, since value was a list of tags. Also corrected the type of the fields.
Declared intention to merge into master (http://lists.debian.org/debian-lint-maint/2011/06/msg00192.html).
- Updated the user manual and the manpages. Also added profile support for lintian-info.
- The tag suppress options no longer excludes using a profile; they now suppress tags from that profile instead.
Profiles can now alter the severity of a tag (since commit e97478f)
Dpkg::Vendor can now be used as a fallback in the absence of dpkg-vendor (since commit 2711536)
The profile implementation will now respect display level again when using a profile and now it uses a profile by default (commit 4309356).
dpkg-vendor replaces the "default" symlink, since this is easier than messing with symlinks in d/rules or postinst. This requires dpkg-dev to be present. Checking if we can use the Dpkg::Vendor perl module to avoid re-opening 626476.
- Renamed overwritable to overridable in the Specification and the code (Thanks Jakub Wilk). This requires a regeneration of profiles.
Added support for non-overridable tags in commit bb9376d. This solves 536364 if merged into master branch.
Fixed a mistake in the profile-generator, where it would use Tags instead of Tag as field name. (commit ecc4fcd)
As of commit bfb7eb6 the initial implementation has a basic support for profile without any extensions using either --profile, LINTIAN_PROFILE or DEB_VENDOR. It currently does not support "default profile" nor does it support any of the extensions.