summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2013-07-25 23:50:14 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2013-07-25 23:52:36 +0200
commit6b495e9251edf626429d143f9fd209884926f44c (patch)
treeb33dd0cc3ee317a8c075df86ddbc47142bfa8ec6
parentb0a12396ef8c0b2b57abe64f2dd5ad35b8707a0d (diff)
downloadnixpkgs-6b495e9251edf626429d143f9fd209884926f44c.tar
nixpkgs-6b495e9251edf626429d143f9fd209884926f44c.tar.gz
nixpkgs-6b495e9251edf626429d143f9fd209884926f44c.tar.bz2
nixpkgs-6b495e9251edf626429d143f9fd209884926f44c.tar.lz
nixpkgs-6b495e9251edf626429d143f9fd209884926f44c.tar.xz
nixpkgs-6b495e9251edf626429d143f9fd209884926f44c.tar.zst
nixpkgs-6b495e9251edf626429d143f9fd209884926f44c.zip
Add nixpkgs-lint
This is a simple tool to scan Nixpkgs for violations of the packaging
guidelines, such as multiple packages with the same name, packages
that lack a description or license, and so on.

To use:

$ nix-env -i nixpkgs-lint
$ cd .../nixpkgs
$ nixpkgs-lint

Current statistics:

Number of packages: 8666
Number of missing maintainers: 3711
Number of missing licenses: 6159
Number of missing descriptions: 1337
Number of bad descriptions: 633
Number of name collisions: 277
-rw-r--r--maintainers/scripts/nixpkgs-lint.nix22
-rwxr-xr-xmaintainers/scripts/nixpkgs-lint.pl115
-rw-r--r--pkgs/top-level/all-packages.nix2
3 files changed, 139 insertions, 0 deletions
diff --git a/maintainers/scripts/nixpkgs-lint.nix b/maintainers/scripts/nixpkgs-lint.nix
new file mode 100644
index 00000000000..5eb7649d58d
--- /dev/null
+++ b/maintainers/scripts/nixpkgs-lint.nix
@@ -0,0 +1,22 @@
+{ stdenv, makeWrapper, perl, perlPackages }:
+
+stdenv.mkDerivation {
+  name = "nixpkgs-lint-1";
+
+  buildInputs = [ makeWrapper perl perlPackages.XMLSimple ];
+
+  unpackPhase = "true";
+  buildPhase = "true";
+
+  installPhase =
+    ''
+      mkdir -p $out/bin
+      cp ${./nixpkgs-lint.pl} $out/bin/nixpkgs-lint
+      wrapProgram $out/bin/nixpkgs-lint --set PERL5LIB $PERL5LIB
+    '';
+
+  meta = {
+    maintainers = [ stdenv.lib.maintainers.eelco ];
+    description = "A utility for Nixpkgs contributors to check Nixpkgs for common errors";
+  };
+}
diff --git a/maintainers/scripts/nixpkgs-lint.pl b/maintainers/scripts/nixpkgs-lint.pl
new file mode 100755
index 00000000000..0b1519ef15c
--- /dev/null
+++ b/maintainers/scripts/nixpkgs-lint.pl
@@ -0,0 +1,115 @@
+#! /run/current-system/sw/bin/perl -w
+
+use strict;
+use List::Util qw(min);
+use XML::Simple qw(:strict);
+use Data::Dumper;
+
+my $filter = "*";
+
+my $xml = `nix-env -f . -qa '$filter' --xml --meta --drv-path`;
+
+my $info = XMLin($xml, KeyAttr => { 'item' => '+attrPath', 'meta' => 'name' }, ForceArray => 1, SuppressEmpty => '' ) or die "cannot parse XML output";
+
+#print Dumper($info);
+
+my %pkgsByName;
+
+foreach my $attr (sort keys %{$info->{item}}) {
+    my $pkg = $info->{item}->{$attr};
+    #print STDERR "attr = $attr, name = $pkg->{name}\n";
+    $pkgsByName{$pkg->{name}} //= [];
+    push @{$pkgsByName{$pkg->{name}}}, $pkg;
+}
+
+# Check meta information.
+print "=== Package meta information ===\n\n";
+my $nrMissingMaintainers = 0;
+my $nrMissingDescriptions = 0;
+my $nrBadDescriptions = 0;
+my $nrMissingLicenses = 0;
+
+foreach my $attr (sort keys %{$info->{item}}) {
+    my $pkg = $info->{item}->{$attr};
+
+    my $pkgName = $pkg->{name};
+    $pkgName =~ s/-[0-9].*//;
+
+    # Check the maintainers.
+    my @maintainers;
+    my $x = $pkg->{meta}->{maintainers};
+    if (defined $x && $x->{type} eq "strings") {
+        @maintainers = map { $_->{value} } @{$x->{string}};
+    } elsif (defined $x->{value}) {
+        @maintainers = ($x->{value});
+    }
+
+    if (scalar @maintainers == 0) {
+        print "$attr: Lacks a maintainer\n";
+        $nrMissingMaintainers++;
+    }
+
+    # Check the license.
+    if (!defined $pkg->{meta}->{license}) {
+        print "$attr: Lacks a license\n";
+        $nrMissingLicenses++;
+    }
+
+    # Check the description.
+    my $description = $pkg->{meta}->{description}->{value};
+    if (!$description) {
+        print "$attr: Lacks a description\n";
+        $nrMissingDescriptions++;
+    } else {
+        my $bad = 0;
+        if ($description =~ /^\s/) {
+            print "$attr: Description starts with whitespace\n";
+            $bad = 1;
+        }
+        if ($description =~ /\s$/) {
+            print "$attr: Description ends with whitespace\n";
+            $bad = 1;
+        }
+        if ($description =~ /\.$/) {
+            print "$attr: Description ends with a period\n";
+            $bad = 1;
+        }
+        if (index(lc($description), lc($attr)) != -1) {
+            print "$attr: Description contains package name\n";
+            $bad = 1;
+        }
+        $nrBadDescriptions++ if $bad;
+    }
+}
+print "\n";
+
+# Find packages that have the same name.
+print "=== Package name collisions ===\n\n";
+
+my $nrCollisions = 0;
+foreach my $name (sort keys %pkgsByName) {
+    my @pkgs = @{$pkgsByName{$name}};
+
+    # Filter attributes that are aliases of each other (e.g. yield the
+    # same derivation path).
+    my %drvsSeen;
+    @pkgs = grep { my $x = $drvsSeen{$_->{drvPath}}; $drvsSeen{$_->{drvPath}} = 1; !defined $x } @pkgs;
+
+    # Filter packages that have a lower priority.
+    my $highest = min (map { $_->{priority} // 0 } @pkgs);
+    @pkgs = grep { ($_->{priority} // 0) == $highest } @pkgs;
+
+    next if scalar @pkgs == 1;
+
+    $nrCollisions++;
+    print "The following attributes evaluate to a package named ‘$name’:\n";
+    print "  ", join(", ", map { $_->{attrPath} } @pkgs), "\n\n";
+}
+
+print "=== Bottom line ===\n";
+print "Number of packages: ", scalar(keys %{$info->{item}}), "\n";
+print "Number of missing maintainers: $nrMissingMaintainers\n";
+print "Number of missing licenses: $nrMissingLicenses\n";
+print "Number of missing descriptions: $nrMissingDescriptions\n";
+print "Number of bad descriptions: $nrBadDescriptions\n";
+print "Number of name collisions: $nrCollisions\n";
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index bffffad649d..300c4bc23fe 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -206,6 +206,8 @@ let
 
   nix-generate-from-cpan = callPackage ../../maintainers/scripts/nix-generate-from-cpan.nix { };
 
+  nixpkgs-lint = callPackage ../../maintainers/scripts/nixpkgs-lint.nix { };
+
 
   ### STANDARD ENVIRONMENT