123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- #!/usr/bin/env perl
- # SPDX-License-Identifier: GPL-2.0
- #
- # Treewide grep for references to files under Documentation, and report
- # non-existing files in stderr.
- use warnings;
- use strict;
- use Getopt::Long qw(:config no_auto_abbrev);
- my $scriptname = $0;
- $scriptname =~ s,.*/([^/]+/),$1,;
- # Parse arguments
- my $help = 0;
- my $fix = 0;
- GetOptions(
- 'fix' => \$fix,
- 'h|help|usage' => \$help,
- );
- if ($help != 0) {
- print "$scriptname [--help] [--fix]\n";
- exit -1;
- }
- # Step 1: find broken references
- print "Finding broken references. This may take a while... " if ($fix);
- my %broken_ref;
- open IN, "git grep 'Documentation/'|"
- or die "Failed to run git grep";
- while (<IN>) {
- next if (!m/^([^:]+):(.*)/);
- my $f = $1;
- my $ln = $2;
- # Makefiles and scripts contain nasty expressions to parse docs
- next if ($f =~ m/Makefile/ || $f =~ m/\.sh$/);
- # Skip this script
- next if ($f eq $scriptname);
- if ($ln =~ m,\b(\S*)(Documentation/[A-Za-z0-9\_\.\,\~/\*\[\]\?+-]*)(.*),) {
- my $prefix = $1;
- my $ref = $2;
- my $base = $2;
- my $extra = $3;
- # some file references are like:
- # /usr/src/linux/Documentation/DMA-{API,mapping}.txt
- # For now, ignore them
- next if ($extra =~ m/^{/);
- # Remove footnotes at the end like:
- # Documentation/devicetree/dt-object-internal.txt[1]
- $ref =~ s/(txt|rst)\[\d+]$/$1/;
- # Remove ending ']' without any '['
- $ref =~ s/\].*// if (!($ref =~ m/\[/));
- # Remove puntuation marks at the end
- $ref =~ s/[\,\.]+$//;
- my $fulref = "$prefix$ref";
- $fulref =~ s/^(\<file|ref)://;
- $fulref =~ s/^[\'\`]+//;
- $fulref =~ s,^\$\(.*\)/,,;
- $base =~ s,.*/,,;
- # Remove URL false-positives
- next if ($fulref =~ m/^http/);
- # Remove sched-pelt false-positive
- next if ($fulref =~ m,^Documentation/scheduler/sched-pelt$,);
- # Discard some build examples from Documentation/target/tcm_mod_builder.txt
- next if ($fulref =~ m,mnt/sdb/lio-core-2.6.git/Documentation/target,);
- # Check if exists, evaluating wildcards
- next if (grep -e, glob("$ref $fulref"));
- # Accept relative Documentation patches for tools/
- if ($f =~ m/tools/) {
- my $path = $f;
- $path =~ s,(.*)/.*,$1,;
- next if (grep -e, glob("$path/$ref $path/$fulref"));
- }
- if ($fix) {
- if (!($ref =~ m/(scripts|Kconfig|Kbuild)/)) {
- $broken_ref{$ref}++;
- }
- } else {
- print STDERR "$f: $fulref\n";
- }
- }
- }
- exit 0 if (!$fix);
- # Step 2: Seek for file name alternatives
- print "Auto-fixing broken references. Please double-check the results\n";
- foreach my $ref (keys %broken_ref) {
- my $new =$ref;
- # get just the basename
- $new =~ s,.*/,,;
- my $f="";
- # usual reason for breakage: DT file moved around
- if ($ref =~ /devicetree/) {
- my $search = $new;
- $search =~ s,^.*/,,;
- $f = qx(find Documentation/devicetree/ -iname "*$search*") if ($search);
- if (!$f) {
- # Manufacturer name may have changed
- $search =~ s/^.*,//;
- $f = qx(find Documentation/devicetree/ -iname "*$search*") if ($search);
- }
- }
- # usual reason for breakage: file renamed to .rst
- if (!$f) {
- $new =~ s/\.txt$/.rst/;
- $f=qx(find . -iname $new) if ($new);
- }
- # usual reason for breakage: use dash or underline
- if (!$f) {
- $new =~ s/[-_]/[-_]/g;
- $f=qx(find . -iname $new) if ($new);
- }
- # Wild guess: seek for the same name on another place
- if (!$f) {
- $f = qx(find . -iname $new) if ($new);
- }
- my @find = split /\s+/, $f;
- if (!$f) {
- print STDERR "ERROR: Didn't find a replacement for $ref\n";
- } elsif (scalar(@find) > 1) {
- print STDERR "WARNING: Won't auto-replace, as found multiple files close to $ref:\n";
- foreach my $j (@find) {
- $j =~ s,^./,,;
- print STDERR " $j\n";
- }
- } else {
- $f = $find[0];
- $f =~ s,^./,,;
- print "INFO: Replacing $ref to $f\n";
- foreach my $j (qx(git grep -l $ref)) {
- qx(sed "s\@$ref\@$f\@g" -i $j);
- }
- }
- }
|