[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: lintian for Emdebian



On Thu, 2008-04-03 at 16:59 -0700, Russ Allbery wrote:
> Neil Williams <codehelp@debian.org> writes:
> 
> We should support a global overrides file or directory.  I'd be happy to
> add that functionality, but it does probably require code changes now that
> I think about this some more.

Yes, it would need to either be duplicated into %info under the $file
key of each package or held as a separate reference and checked in
check_overrides() of Tags.pm or simply duplicate the existing code to
read package overrides:
	unless ($no_override) {
            if (open(O, '<', "$base/override")) {
                while (<O>) 
which means reading the global override file more than once.

I've played with a global override directory and I've included some
working perl code below. However, there are problems with using this as
a global and I've also included sample code for an alternative method
that does not involve a global directory but actually retains complete
control over the overrides within the specific check script itself. (So
this email is a bit long.) :-)

> > However, I'm finding it impossible to override the manpage warnings
> > without removing all the manpages checks with -X :
> >
> > I don't actually need the manpages checks but I would like to not have
> > to alias lintian to lintian -X manpages.
> 
> Where are you adding the overrides?  Is it possible that the manpage check
> script is happening before your overrides are added?

> > Is there a way of implementing '-X' within the check scripts? (It would
> > save time if I could drop entire scripts like manpages and replace with
> > a simple check that /usr/share/man/ is empty).
> 
> You could divert the manpages file, but there isn't any way to skip an
> entire check from within another check (in part because the order in which
> the checks are run is not, I think, fully deterministic, although I could
> be wrong -- I think it runs them in glob order).

Not AFAICT at the readdir stage:
$ perl -le 'opendir DIR, "/usr/share/lintian/checks"; print join " ", readdir DIR'

emdebian appears there before manpages.
. .. changelog-file.desc po-debconf.desc emdebian init.d scripts
copyright-file.desc emdebian.desc menu-format description.desc
common_data.pm shared-libs md5sums etcfiles menu-format.desc cruft.desc
debconf files standards-version menus.desc fields conffiles.desc
standards-version.desc manpages.desc conffiles control-file.desc
etcfiles.desc nmu.desc huge-usr-share.desc debconf.desc infofiles
files.desc control-files description fields.desc cruft init.d.desc nmu
debian-readme.desc copyright-file menus infofiles.desc debhelper rules
manpages

No, the problem appears to be only when running the checks due to the
arbitrary way that perl indexes hashes:

# perform checks
for my $check (keys %checks) {
    my $ci = $check_info{$check};

Sorting those keys puts manpages behind emdebian but then puts copyright
ahead of emdebian which means that the copyright overrides are missed
instead. :-(

I can hack around it by then making the emdebian checks to be 00emdebian
etc. but that is ugly.

> I think the right approach may be to create a directory
> /usr/share/lintian/overrides/global and load all files in that directory
> in addition to the regular overrides.

Even that needs some flexibility because I currently use
Tags::add_override to selectively override tags dependent on the type of
package so that I don't get too many unused overrides.

My current override set is:

binary-or-shlib-defines-rpath
binary-without-manpage
build-depends-indep-without-arch-indep
changelog-should-mention-nmu
debian-files-list-in-source
debian-rules-missing-required-target
extended-description-is-empty
native-package-with-dash-version
no-copyright-file
no-md5sums-control-file
python-script-but-no-python-dep
source-nmu-has-incorrect-version-number

Of those, some apply only to the source package, some only to binaries,
some only to the Emdebian TDebs that are a completely different issue
(eventually, those will need something like the current lintian support
for udebs).

e.g.

elsif (($info =~ /GNU message catalog/) and ($tdeb > 0))
{
	Tags::add_override ("extended-description-is-empty");
	Tags::add_override ("no-md5sums-control-file");
	Tags::add_override ("no-copyright-file");
	# need TDeb checks here.
	Tags::add_override ("debian-rules-missing-required-target *");
	# might want to fix this one.
	Tags::add_override ("debian-files-list-in-source");
	Tags::add_override ("native-package-with-dash-version");

This code works for me (without the extra flexibility):
Adding to the existing code at:

	unless ($no_override) {
            if (open(O, '<', "$base/override")) {
                while (<O>) {
                    chomp;
                    next if m,^\s*(\#|\z),o;
                    s/^\s+//o;
                    s/\s+$//o;
                    s/\s+/ /go;
                    my $override = $_;
                    $override =~ s/^\Q$pkg\E( \Q$long_type\E)?: //;
                    if ($override eq '' or $override !~ /^[\w0-9.+-]+(\s+.*)?$/) {
                        tag ('malformed-override', $_);
                    } else {
                        Tags::add_override($override);
                    }
                }
                close(O);
            }

# add the new code

            if (opendir(ODIR, "$LINTIAN_ROOT/overrides/global/")) {
                my @g_override=grep(!/^\.\.?$/, readdir ODIR);
                closedir (ODIR);
                foreach my $g_file (sort @g_override)
                {
                    open (O, "$LINTIAN_ROOT/overrides/global/$g_file")
                      or die ("$!");
                    while (<O>) {
                    next if m,^\s*(\#|\z),o;
                    s/^\s+//o;
                    s/\s+$//o;
                    s/\s+/ /go;
                    my $override = $_;
                    $override =~ s/^\Q$pkg\E( \Q$long_type\E)?: //;
                    if ($override eq '' or $override !~ /^[\w0-9.+-]+(\s+.*)?$/) {
                        tag ('malformed-override', $_);
                    } else {
                        Tags::add_override($override);
                    }
                }
                close(O);
                }
             }


TDebs are OK as they are for now, so
$ cat /usr/share/lintian/overrides/global/emdebian.overrides
binary-or-shlib-defines-rpath
binary-without-manpage
build-depends-indep-without-arch-indep
no-copyright-file
python-script-but-no-python-dep

It would be good if that could be:

bin: binary-or-shlib-defines-rpath
bin: binary-without-manpage
src: build-depends-indep-without-arch-indep
any: no-copyright-file
any: python-script-but-no-python-dep

but the above code works as-is and I don't think I'll need more than a
couple of these global overrides (in fact, I can probably do without a
few of the current ones).

What the code does not achieve is only loading this global override file
upon request of the check script or under defined circumstances.

I don't want to remove these warnings from lintian when, e.g. sponsoring
packages for Debian - only when building packages for Emdebian.

To do that, I'd need this code to be wrapped in a command-line option
because whenever the check script is loaded it will be too late to
prevent the existing checks from being removed.

Alternative:
============

It would be a lot cleaner if I could disable other checks within the
check script itself by making Tags::add_override reliable and
predictable. I wouldn't need a global override directory if there was a
hook in lintian to set overrides *before* any other &run() subroutines
are actually run (including my own). i.e. a second function in the check
script Package::foo that lintian calls when the package has been
unpacked but before any &run() functions are called.

i.e. split the current loop at 'for my $check (keys %checks)' so that it
gets as far as Checker::runcheck but instead, it loads the overrides,
returns to the start of the loop and then restarts a second loop to run
Checker::runcheck so that all the overrides are set when the package is
already unpacked but before any checks are actually run.

Something similar to runcheck() in Checker.pm called, maybe,
load_overrides() ? (Would that mean altering each check script to have a
dummy load_overrides()? or the register() function could be modified to
look for a flag that says that the check script wants to pre-register
the overrides?)

in lintian, add:

       my $returnvalue = Checker::load_overrides($pkg, $long_type, $check);
       # Set exit_code correctly if there was not yet an exit code
       $exit_code = $returnvalue unless $exit_code;
    # end the loop here to ensure all overrides are set before calling
    # run() for any check script.
    }
    # probably need to specify that load_overrides doesn't do any chdir operations
    for my $check (keys %checks) {

above:

	my $returnvalue = Checker::runcheck($pkg, $long_type, $check);
	# Set exit_code correctly if there was not yet an exit code
	$exit_code = $returnvalue unless $exit_code;

In Checker.pm:
sub load_overrides {
	my $pkg = shift;
	my $type = shift;
	my $name = shift;

	# Will be set to 2 if error is encountered
	my $return = 0;

	print "N: Setting overrides for: $name ...\n" if $debug;

	my $check = $checks{$name};

	# require has a anti-require-twice cache
	require "$LINTIAN_ROOT/checks/$name";

	#print STDERR "Now loading overrides for $name...\n";
	$name =~ s/[-.]/_/g;
	eval { &{'Lintian::'.$name.'::set'}($pkg, $type) };
	if ( $@ ) {
	    print STDERR $@;
	    print STDERR "internal error: cannot set $name overrides on package $pkg\n";
	    $return = 2;
	}

	return $return;
}


I'd use something like this:

sub set {
	our $arch;
	my $pkg = shift;
	my $type = shift;
	my $tdeb = 0;
	my $build = `dpkg-architecture -qDEB_BUILD_ARCH`;
	chomp($build);
	$tdeb = 1 if ($pkg =~ /locale/);
	# only use any of the following if this is an Emdebian package.
	my $version = "";
	open (VERSION, '<', 'fields/version') or return;
	$version = <VERSION>;
	close (VERSION);
	return unless $version =~ /em[0-9]+$/;
	if ($type eq "source")
	{
		Tags::add_override ("debian-rules-missing-required-target");
		# might want to fix this one.
		Tags::add_override ("debian-files-list-in-source");
		Tags::add_override ("native-package-with-dash-version");
		Tags::add_override ("build-depends-indep-without-arch-indep");
		Tags::add_override ("source-nmu-has-incorrect-version-number");
		Tags::add_override ("changelog-should-mention-nmu");
		return;
	}
	if ($tdeb > 0)
	{
		Tags::add_override ("extended-description-is-empty");
		Tags::add_override ("no-md5sums-control-file");
		Tags::add_override ("no-copyright-file");
		# need TDeb checks here.
		Tags::add_override ("debian-rules-missing-required-target *");
		# might want to fix this one.
		Tags::add_override ("debian-files-list-in-source");
		Tags::add_override ("native-package-with-dash-version");
		return;
	}
	Tags::add_override ("no-copyright-file");
	Tags::add_override ("python-script-but-no-python-dep");
	Tags::add_override ("binary-without-manpage");
	Tags::add_override ("binary-or-shlib-defines-rpath");
	Tags::add_override ("build-depends-indep-without-arch-indep");
}

and then I could remove all the Tags::add_override calls within the
actual &run() function.

This way, I would never have to worry about people inadvertently running
Emdebian lintian checks on Debian packages or vice-versa because the
ability to run the emdebian check script is entirely determined by the
settings within the emdebian check script itself. It would also be a lot
easier to maintain such a check script because the overrides are
separate from the checks.

-- 


Neil Williams
=============
http://www.data-freedom.org/
http://www.nosoftwarepatents.com/
http://www.linux.codehelp.co.uk/


Attachment: signature.asc
Description: This is a digitally signed message part


Reply to: