Blame view

scripts/documentation-file-ref-check 3.72 KB
d26560950   Mauro Carvalho Chehab   scripts/documenta...
1
2
3
  #!/usr/bin/env perl
  # SPDX-License-Identifier: GPL-2.0
  #
e8939222d   Jani Nikula   Documentation: ad...
4
5
  # Treewide grep for references to files under Documentation, and report
  # non-existing files in stderr.
d26560950   Mauro Carvalho Chehab   scripts/documenta...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  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) {
40fc3eb05   Mauro Carvalho Chehab   scripts/documenta...
23
24
      print "$scriptname [--help] [--fix]
  ";
d26560950   Mauro Carvalho Chehab   scripts/documenta...
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
      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;
2d69708f9   Mauro Carvalho Chehab   scripts/documenta...
40
41
  	# Makefiles and scripts contain nasty expressions to parse docs
  	next if ($f =~ m/Makefile/ || $f =~ m/\.sh$/);
d26560950   Mauro Carvalho Chehab   scripts/documenta...
42
43
  	# Skip this script
  	next if ($f eq $scriptname);
2d69708f9   Mauro Carvalho Chehab   scripts/documenta...
44
  	if ($ln =~ m,\b(\S*)(Documentation/[A-Za-z0-9\_\.\,\~/\*\[\]\?+-]*)(.*),) {
d26560950   Mauro Carvalho Chehab   scripts/documenta...
45
46
47
  		my $prefix = $1;
  		my $ref = $2;
  		my $base = $2;
2d69708f9   Mauro Carvalho Chehab   scripts/documenta...
48
49
50
51
52
53
54
55
56
57
58
59
60
  		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/\[/));
d26560950   Mauro Carvalho Chehab   scripts/documenta...
61

2d69708f9   Mauro Carvalho Chehab   scripts/documenta...
62
  		# Remove puntuation marks at the end
d26560950   Mauro Carvalho Chehab   scripts/documenta...
63
64
65
66
67
68
69
70
71
72
73
  		$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/);
5d395fa63   Mauro Carvalho Chehab   scripts/documenta...
74
75
  		# Remove sched-pelt false-positive
  		next if ($fulref =~ m,^Documentation/scheduler/sched-pelt$,);
d25c06344   Mauro Carvalho Chehab   scripts/documenta...
76
77
  		# Discard some build examples from Documentation/target/tcm_mod_builder.txt
  		next if ($fulref =~ m,mnt/sdb/lio-core-2.6.git/Documentation/target,);
d26560950   Mauro Carvalho Chehab   scripts/documenta...
78
79
  		# Check if exists, evaluating wildcards
  		next if (grep -e, glob("$ref $fulref"));
a78513c67   Mauro Carvalho Chehab   scripts/documenta...
80
81
82
83
84
85
  		# 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"));
  		}
d26560950   Mauro Carvalho Chehab   scripts/documenta...
86
  		if ($fix) {
be600e5ac   Mauro Carvalho Chehab   scripts/documenta...
87
  			if (!($ref =~ m/(scripts|Kconfig|Kbuild)/)) {
d26560950   Mauro Carvalho Chehab   scripts/documenta...
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  				$broken_ref{$ref}++;
  			}
  		} else {
  			print STDERR "$f: $fulref
  ";
  		}
  	}
  }
  
  exit 0 if (!$fix);
  
  # Step 2: Seek for file name alternatives
  print "Auto-fixing broken references. Please double-check the results
  ";
  
  foreach my $ref (keys %broken_ref) {
  	my $new =$ref;
  
  	# get just the basename
  	$new =~ s,.*/,,;
d26560950   Mauro Carvalho Chehab   scripts/documenta...
108
  	my $f="";
be600e5ac   Mauro Carvalho Chehab   scripts/documenta...
109
110
111
112
113
114
115
116
117
118
119
  	# 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);
  		}
  	}
d26560950   Mauro Carvalho Chehab   scripts/documenta...
120
121
122
123
124
125
  
  	# usual reason for breakage: file renamed to .rst
  	if (!$f) {
  		$new =~ s/\.txt$/.rst/;
  		$f=qx(find . -iname $new) if ($new);
  	}
e1f319fe4   Mauro Carvalho Chehab   scripts/documenta...
126
127
128
129
130
  	# usual reason for breakage: use dash or underline
  	if (!$f) {
  		$new =~ s/[-_]/[-_]/g;
  		$f=qx(find . -iname $new) if ($new);
  	}
be600e5ac   Mauro Carvalho Chehab   scripts/documenta...
131
132
133
134
  	# Wild guess: seek for the same name on another place
  	if (!$f) {
  		$f = qx(find . -iname $new) if ($new);
  	}
d26560950   Mauro Carvalho Chehab   scripts/documenta...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
  	my @find = split /\s+/, $f;
  
  	if (!$f) {
  		print STDERR "ERROR: Didn't find a replacement for $ref
  ";
  	} elsif (scalar(@find) > 1) {
  		print STDERR "WARNING: Won't auto-replace, as found multiple files close to $ref:
  ";
  		foreach my $j (@find) {
  			$j =~ s,^./,,;
  			print STDERR "    $j
  ";
  		}
  	} else {
  		$f = $find[0];
  		$f =~ s,^./,,;
  		print "INFO: Replacing $ref to $f
  ";
  		foreach my $j (qx(git grep -l $ref)) {
  			qx(sed "s\@$ref\@$f\@g" -i $j);
  		}
  	}
  }