xref: /freebsd/contrib/pam-krb5/tests/docs/spdx-license-t (revision bf6873c5786e333d679a7838d28812febf479a8a)
1*bf6873c5SCy Schubert#!/usr/bin/perl
2*bf6873c5SCy Schubert#
3*bf6873c5SCy Schubert# Check source files for SPDX-License-Identifier fields.
4*bf6873c5SCy Schubert#
5*bf6873c5SCy Schubert# Examine all source files in a distribution to check that they contain an
6*bf6873c5SCy Schubert# SPDX-License-Identifier field.  This does not check the syntax or whether
7*bf6873c5SCy Schubert# the identifiers are valid.
8*bf6873c5SCy Schubert#
9*bf6873c5SCy Schubert# The canonical version of this file is maintained in the rra-c-util package,
10*bf6873c5SCy Schubert# which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
11*bf6873c5SCy Schubert#
12*bf6873c5SCy Schubert# Copyright 2018-2021 Russ Allbery <eagle@eyrie.org>
13*bf6873c5SCy Schubert#
14*bf6873c5SCy Schubert# Permission is hereby granted, free of charge, to any person obtaining a
15*bf6873c5SCy Schubert# copy of this software and associated documentation files (the "Software"),
16*bf6873c5SCy Schubert# to deal in the Software without restriction, including without limitation
17*bf6873c5SCy Schubert# the rights to use, copy, modify, merge, publish, distribute, sublicense,
18*bf6873c5SCy Schubert# and/or sell copies of the Software, and to permit persons to whom the
19*bf6873c5SCy Schubert# Software is furnished to do so, subject to the following conditions:
20*bf6873c5SCy Schubert#
21*bf6873c5SCy Schubert# The above copyright notice and this permission notice shall be included in
22*bf6873c5SCy Schubert# all copies or substantial portions of the Software.
23*bf6873c5SCy Schubert#
24*bf6873c5SCy Schubert# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25*bf6873c5SCy Schubert# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26*bf6873c5SCy Schubert# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
27*bf6873c5SCy Schubert# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28*bf6873c5SCy Schubert# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29*bf6873c5SCy Schubert# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30*bf6873c5SCy Schubert# DEALINGS IN THE SOFTWARE.
31*bf6873c5SCy Schubert#
32*bf6873c5SCy Schubert# SPDX-License-Identifier: MIT
33*bf6873c5SCy Schubert
34*bf6873c5SCy Schubertuse 5.010;
35*bf6873c5SCy Schubertuse strict;
36*bf6873c5SCy Schubertuse warnings;
37*bf6873c5SCy Schubert
38*bf6873c5SCy Schubertuse lib "$ENV{C_TAP_SOURCE}/tap/perl";
39*bf6873c5SCy Schubert
40*bf6873c5SCy Schubertuse Test::RRA qw(skip_unless_automated);
41*bf6873c5SCy Schubertuse Test::RRA::Automake qw(all_files automake_setup);
42*bf6873c5SCy Schubert
43*bf6873c5SCy Schubertuse File::Basename qw(basename);
44*bf6873c5SCy Schubertuse Test::More;
45*bf6873c5SCy Schubert
46*bf6873c5SCy Schubert# File name (the file without any directory component) and path patterns to
47*bf6873c5SCy Schubert# skip for this check.
48*bf6873c5SCy Schubert## no critic (RegularExpressions::ProhibitFixedStringMatches)
49*bf6873c5SCy Schubertmy @IGNORE = (
50*bf6873c5SCy Schubert    qr{ \A LICENSE \z }xms,             # Generated file with no license itself
51*bf6873c5SCy Schubert    qr{ \A (NEWS|THANKS|TODO) \z }xms,  # Package license should be fine
52*bf6873c5SCy Schubert    qr{ \A README ( [.] .* )? \z }xms,  # Package license should be fine
53*bf6873c5SCy Schubert    qr{ \A (Makefile|libtool) \z }xms,  # Generated file
54*bf6873c5SCy Schubert    qr{ ~ \z }xms,                      # Backup files
55*bf6873c5SCy Schubert    qr{ [.] l?a \z }xms,                # Created by libtool
56*bf6873c5SCy Schubert    qr{ [.] o \z }xms,                  # Compiler objects
57*bf6873c5SCy Schubert    qr{ [.] output \z }xms,             # Test data
58*bf6873c5SCy Schubert);
59*bf6873c5SCy Schubertmy @IGNORE_PATHS = (
60*bf6873c5SCy Schubert    qr{ \A debian/ }xms,                       # Found in debian/* branches
61*bf6873c5SCy Schubert    qr{ \A docs/metadata/ }xms,                # Package license should be fine
62*bf6873c5SCy Schubert    qr{ \A docs/protocol[.](html|txt) \z }xms, # Generated by xml2rfc
63*bf6873c5SCy Schubert    qr{ \A m4/ (libtool|lt.*) [.] m4 \z }xms,  # Files from Libtool
64*bf6873c5SCy Schubert    qr{ \A perl/Build \z }xms,                 # Perl build files
65*bf6873c5SCy Schubert    qr{ \A perl/MANIFEST \z }xms,              # Perl build files
66*bf6873c5SCy Schubert    qr{ \A perl/MYMETA [.] }xms,               # Perl build files
67*bf6873c5SCy Schubert    qr{ \A perl/blib/ }xms,                    # Perl build files
68*bf6873c5SCy Schubert    qr{ \A perl/cover_db/ }xms,                # Perl test files
69*bf6873c5SCy Schubert    qr{ \A perl/_build }xms,                   # Perl build files
70*bf6873c5SCy Schubert    qr{ \A php/Makefile [.] global \z }xms,    # Created by phpize
71*bf6873c5SCy Schubert    qr{ \A php/autom4te [.] cache/ }xms,       # Created by phpize
72*bf6873c5SCy Schubert    qr{ \A php/acinclude [.] m4 \z }xms,       # Created by phpize
73*bf6873c5SCy Schubert    qr{ \A php/build/ }xms,                    # Created by phpize
74*bf6873c5SCy Schubert    qr{ \A php/config [.] (guess|sub) \z }xms, # Created by phpize
75*bf6873c5SCy Schubert    qr{ \A php/configure [.] (ac|in) \z }xms,  # Created by phpize
76*bf6873c5SCy Schubert    qr{ \A php/ltmain [.] sh \z }xms,          # Created by phpize
77*bf6873c5SCy Schubert    qr{ \A php/run-tests [.] php \z }xms,      # Created by phpize
78*bf6873c5SCy Schubert    qr{ \A python/ .* [.] egg-info/ }xms,      # Python build files
79*bf6873c5SCy Schubert    qr{ \A tests/config/ (?!README) }xms,      # Test configuration
80*bf6873c5SCy Schubert    qr{ \A tests/tmp/ }xms,                    # Temporary test files
81*bf6873c5SCy Schubert);
82*bf6873c5SCy Schubert## use critic
83*bf6873c5SCy Schubert
84*bf6873c5SCy Schubert# Only run this test during automated testing, since failure doesn't indicate
85*bf6873c5SCy Schubert# any user-noticable flaw in the package itself.
86*bf6873c5SCy Schubertskip_unless_automated('SPDX identifier tests');
87*bf6873c5SCy Schubert
88*bf6873c5SCy Schubert# Set up Automake testing.
89*bf6873c5SCy Schubertautomake_setup();
90*bf6873c5SCy Schubert
91*bf6873c5SCy Schubert# Check a single file for an occurrence of the string.
92*bf6873c5SCy Schubert#
93*bf6873c5SCy Schubert# $path - Path to the file
94*bf6873c5SCy Schubert#
95*bf6873c5SCy Schubert# Returns: undef
96*bf6873c5SCy Schubertsub check_file {
97*bf6873c5SCy Schubert    my ($path) = @_;
98*bf6873c5SCy Schubert    my $filename = basename($path);
99*bf6873c5SCy Schubert
100*bf6873c5SCy Schubert    # Ignore files in the whitelist and binary files.
101*bf6873c5SCy Schubert    for my $pattern (@IGNORE) {
102*bf6873c5SCy Schubert        return if $filename =~ $pattern;
103*bf6873c5SCy Schubert    }
104*bf6873c5SCy Schubert    for my $pattern (@IGNORE_PATHS) {
105*bf6873c5SCy Schubert        return if $path =~ $pattern;
106*bf6873c5SCy Schubert    }
107*bf6873c5SCy Schubert    return if !-T $path;
108*bf6873c5SCy Schubert
109*bf6873c5SCy Schubert    # Scan the file.
110*bf6873c5SCy Schubert    my ($saw_legacy_notice, $saw_spdx, $skip_spdx);
111*bf6873c5SCy Schubert    open(my $file, '<', $path) or BAIL_OUT("Cannot open $path: $!");
112*bf6873c5SCy Schubert    while (defined(my $line = <$file>)) {
113*bf6873c5SCy Schubert        if ($line =~ m{ Generated [ ] by [ ] libtool [ ] }xms) {
114*bf6873c5SCy Schubert            close($file) or BAIL_OUT("Cannot close $path: $!");
115*bf6873c5SCy Schubert            return;
116*bf6873c5SCy Schubert        }
117*bf6873c5SCy Schubert        if ($line =~ m{ \b See \s+ LICENSE \s+ for \s+ licensing }xms) {
118*bf6873c5SCy Schubert            $saw_legacy_notice = 1;
119*bf6873c5SCy Schubert        }
120*bf6873c5SCy Schubert        if ($line =~ m{ \b SPDX-License-Identifier: \s+ \S+ }xms) {
121*bf6873c5SCy Schubert            $saw_spdx = 1;
122*bf6873c5SCy Schubert            last;
123*bf6873c5SCy Schubert        }
124*bf6873c5SCy Schubert        if ($line =~ m{ no \s SPDX-License-Identifier \s registered }xms) {
125*bf6873c5SCy Schubert            $skip_spdx = 1;
126*bf6873c5SCy Schubert            last;
127*bf6873c5SCy Schubert        }
128*bf6873c5SCy Schubert    }
129*bf6873c5SCy Schubert    close($file) or BAIL_OUT("Cannot close $path: $!");
130*bf6873c5SCy Schubert
131*bf6873c5SCy Schubert    # If there is a legacy license notice, report a failure regardless of file
132*bf6873c5SCy Schubert    # size.  Otherwise, skip files under 1KB.  They can be rolled up into the
133*bf6873c5SCy Schubert    # overall project license and the license notice may be a substantial
134*bf6873c5SCy Schubert    # portion of the file size.
135*bf6873c5SCy Schubert    if ($saw_legacy_notice) {
136*bf6873c5SCy Schubert        ok(!$saw_legacy_notice, "$path has legacy license notice");
137*bf6873c5SCy Schubert    } else {
138*bf6873c5SCy Schubert        ok($saw_spdx || $skip_spdx || -s $path < 1024, $path);
139*bf6873c5SCy Schubert    }
140*bf6873c5SCy Schubert    return;
141*bf6873c5SCy Schubert}
142*bf6873c5SCy Schubert
143*bf6873c5SCy Schubert# Scan every file.  We don't declare a plan since we skip a lot of files and
144*bf6873c5SCy Schubert# don't want to precalculate the file list.
145*bf6873c5SCy Schubertmy @paths = all_files();
146*bf6873c5SCy Schubertfor my $path (@paths) {
147*bf6873c5SCy Schubert    check_file($path);
148*bf6873c5SCy Schubert}
149*bf6873c5SCy Schubertdone_testing();
150