Blame view

scripts/documentation-file-ref-check 5.55 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
  use warnings;
  use strict;
  use Getopt::Long qw(:config no_auto_abbrev);
aeaacbfed   Mauro Carvalho Chehab   scripts/documenta...
9
10
11
12
  # NOTE: only add things here when the file was gone, but the text wants
  # to mention a past documentation file, for example, to give credits for
  # the original work.
  my %false_positives = (
ce5c5d650   Mauro Carvalho Chehab   scsi: docs: conve...
13
  	"Documentation/scsi/scsi_mid_low_api.rst" => "Documentation/Configure.help",
aeaacbfed   Mauro Carvalho Chehab   scripts/documenta...
14
15
  	"drivers/vhost/vhost.c" => "Documentation/virtual/lguest/lguest.c",
  );
d26560950   Mauro Carvalho Chehab   scripts/documenta...
16
17
18
19
20
21
  my $scriptname = $0;
  $scriptname =~ s,.*/([^/]+/),$1,;
  
  # Parse arguments
  my $help = 0;
  my $fix = 0;
b1663d7e3   Mauro Carvalho Chehab   docs: Kbuild/Make...
22
23
24
  my $warn = 0;
  
  if (! -d ".git") {
d98dbbe0d   Tiezhu Yang   scripts: document...
25
26
  	printf "Warning: can't check if file exists, as this is not a git tree
  ";
b1663d7e3   Mauro Carvalho Chehab   docs: Kbuild/Make...
27
28
  	exit 0;
  }
d26560950   Mauro Carvalho Chehab   scripts/documenta...
29
30
31
  
  GetOptions(
  	'fix' => \$fix,
b1663d7e3   Mauro Carvalho Chehab   docs: Kbuild/Make...
32
  	'warn' => \$warn,
d26560950   Mauro Carvalho Chehab   scripts/documenta...
33
34
35
36
  	'h|help|usage' => \$help,
  );
  
  if ($help != 0) {
40fc3eb05   Mauro Carvalho Chehab   scripts/documenta...
37
38
      print "$scriptname [--help] [--fix]
  ";
d26560950   Mauro Carvalho Chehab   scripts/documenta...
39
40
41
42
43
44
45
      exit -1;
  }
  
  # Step 1: find broken references
  print "Finding broken references. This may take a while...  " if ($fix);
  
  my %broken_ref;
894ee5ff8   Mauro Carvalho Chehab   scripts/documenta...
46
47
48
49
50
51
  my $doc_fix = 0;
  
  open IN, "git grep ':doc:\`' Documentation/|"
       or die "Failed to run git grep";
  while (<IN>) {
  	next if (!m,^([^:]+):.*\:doc\:\`([^\`]+)\`,);
290d53889   Mauro Carvalho Chehab   scripts: document...
52
  	next if (m,sphinx/,);
894ee5ff8   Mauro Carvalho Chehab   scripts/documenta...
53

290d53889   Mauro Carvalho Chehab   scripts: document...
54
  	my $file = $1;
894ee5ff8   Mauro Carvalho Chehab   scripts/documenta...
55
56
57
58
59
60
61
  	my $d = $1;
  	my $doc_ref = $2;
  
  	my $f = $doc_ref;
  
  	$d =~ s,(.*/).*,$1,;
  	$f =~ s,.*\<([^\>]+)\>,$1,;
290d53889   Mauro Carvalho Chehab   scripts: document...
62
63
64
65
66
67
  	if ($f =~ m,^/,) {
  		$f = "$f.rst";
  		$f =~ s,^/,Documentation/,;
  	} else {
  		$f = "$d$f.rst";
  	}
894ee5ff8   Mauro Carvalho Chehab   scripts/documenta...
68
69
70
71
72
73
74
75
76
  
  	next if (grep -e, glob("$f"));
  
  	if ($fix && !$doc_fix) {
  		print STDERR "
  WARNING: Currently, can't fix broken :doc:`` fields
  ";
  	}
  	$doc_fix++;
290d53889   Mauro Carvalho Chehab   scripts: document...
77
78
  	print STDERR "$file: :doc:`$doc_ref`
  ";
894ee5ff8   Mauro Carvalho Chehab   scripts/documenta...
79
80
  }
  close IN;
d26560950   Mauro Carvalho Chehab   scripts/documenta...
81
82
83
84
85
86
87
  open IN, "git grep 'Documentation/'|"
       or die "Failed to run git grep";
  while (<IN>) {
  	next if (!m/^([^:]+):(.*)/);
  
  	my $f = $1;
  	my $ln = $2;
fe3e4b9c6   Mauro Carvalho Chehab   scripts/documenta...
88
89
  	# On linux-next, discard the Next/ directory
  	next if ($f =~ m,^Next/,);
2d69708f9   Mauro Carvalho Chehab   scripts/documenta...
90
91
  	# Makefiles and scripts contain nasty expressions to parse docs
  	next if ($f =~ m/Makefile/ || $f =~ m/\.sh$/);
d26560950   Mauro Carvalho Chehab   scripts/documenta...
92
93
  	# Skip this script
  	next if ($f eq $scriptname);
407b584d1   Mauro Carvalho Chehab   scripts/documenta...
94
95
  	# Ignore the dir where documentation will be built
  	next if ($ln =~ m,\b(\S*)Documentation/output,);
2d69708f9   Mauro Carvalho Chehab   scripts/documenta...
96
  	if ($ln =~ m,\b(\S*)(Documentation/[A-Za-z0-9\_\.\,\~/\*\[\]\?+-]*)(.*),) {
d26560950   Mauro Carvalho Chehab   scripts/documenta...
97
98
99
  		my $prefix = $1;
  		my $ref = $2;
  		my $base = $2;
2d69708f9   Mauro Carvalho Chehab   scripts/documenta...
100
101
102
103
104
105
106
107
108
109
110
111
112
  		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...
113

2d69708f9   Mauro Carvalho Chehab   scripts/documenta...
114
  		# Remove puntuation marks at the end
d26560950   Mauro Carvalho Chehab   scripts/documenta...
115
116
117
118
119
120
121
122
123
124
125
  		$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...
126
127
  		# Remove sched-pelt false-positive
  		next if ($fulref =~ m,^Documentation/scheduler/sched-pelt$,);
4ca9bc225   Mauro Carvalho Chehab   docs: target: con...
128
  		# Discard some build examples from Documentation/target/tcm_mod_builder.rst
d25c06344   Mauro Carvalho Chehab   scripts/documenta...
129
  		next if ($fulref =~ m,mnt/sdb/lio-core-2.6.git/Documentation/target,);
d26560950   Mauro Carvalho Chehab   scripts/documenta...
130
131
  		# Check if exists, evaluating wildcards
  		next if (grep -e, glob("$ref $fulref"));
a78513c67   Mauro Carvalho Chehab   scripts/documenta...
132
133
134
135
  		# Accept relative Documentation patches for tools/
  		if ($f =~ m/tools/) {
  			my $path = $f;
  			$path =~ s,(.*)/.*,$1,;
4904aeed9   Mauro Carvalho Chehab   scripts/documenta...
136
  			next if (grep -e, glob("$path/$ref $path/../$ref $path/$fulref"));
a78513c67   Mauro Carvalho Chehab   scripts/documenta...
137
  		}
aeaacbfed   Mauro Carvalho Chehab   scripts/documenta...
138
139
140
141
  		# Discard known false-positives
  		if (defined($false_positives{$f})) {
  			next if ($false_positives{$f} eq $fulref);
  		}
d26560950   Mauro Carvalho Chehab   scripts/documenta...
142
  		if ($fix) {
be600e5ac   Mauro Carvalho Chehab   scripts/documenta...
143
  			if (!($ref =~ m/(scripts|Kconfig|Kbuild)/)) {
d26560950   Mauro Carvalho Chehab   scripts/documenta...
144
145
  				$broken_ref{$ref}++;
  			}
b1663d7e3   Mauro Carvalho Chehab   docs: Kbuild/Make...
146
147
148
  		} elsif ($warn) {
  			print STDERR "Warning: $f references a file that doesn't exist: $fulref
  ";
d26560950   Mauro Carvalho Chehab   scripts/documenta...
149
150
151
152
153
154
  		} else {
  			print STDERR "$f: $fulref
  ";
  		}
  	}
  }
894ee5ff8   Mauro Carvalho Chehab   scripts/documenta...
155
  close IN;
d26560950   Mauro Carvalho Chehab   scripts/documenta...
156
157
158
159
160
161
162
163
164
  
  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;
9e78e7fc0   Mauro Carvalho Chehab   scripts/documenta...
165
166
167
  	my $basedir = ".";
  	# On translations, only seek inside the translations directory
  	$basedir  = $1 if ($ref =~ m,(Documentation/translations/[^/]+),);
d26560950   Mauro Carvalho Chehab   scripts/documenta...
168
169
  	# get just the basename
  	$new =~ s,.*/,,;
d26560950   Mauro Carvalho Chehab   scripts/documenta...
170
  	my $f="";
be600e5ac   Mauro Carvalho Chehab   scripts/documenta...
171
172
  	# usual reason for breakage: DT file moved around
  	if ($ref =~ /devicetree/) {
0ca862e6f   Mauro Carvalho Chehab   scripts/documenta...
173
  		# usual reason for breakage: DT file renamed to .yaml
be600e5ac   Mauro Carvalho Chehab   scripts/documenta...
174
  		if (!$f) {
0ca862e6f   Mauro Carvalho Chehab   scripts/documenta...
175
176
177
178
179
180
181
182
  			my $new_ref = $ref;
  			$new_ref =~ s/\.txt$/.yaml/;
  			$f=$new_ref if (-f $new_ref);
  		}
  
  		if (!$f) {
  			my $search = $new;
  			$search =~ s,^.*/,,;
be600e5ac   Mauro Carvalho Chehab   scripts/documenta...
183
  			$f = qx(find Documentation/devicetree/ -iname "*$search*") if ($search);
0ca862e6f   Mauro Carvalho Chehab   scripts/documenta...
184
185
186
187
188
  			if (!$f) {
  				# Manufacturer name may have changed
  				$search =~ s/^.*,//;
  				$f = qx(find Documentation/devicetree/ -iname "*$search*") if ($search);
  			}
be600e5ac   Mauro Carvalho Chehab   scripts/documenta...
189
190
  		}
  	}
d26560950   Mauro Carvalho Chehab   scripts/documenta...
191
192
193
194
  
  	# usual reason for breakage: file renamed to .rst
  	if (!$f) {
  		$new =~ s/\.txt$/.rst/;
9e78e7fc0   Mauro Carvalho Chehab   scripts/documenta...
195
  		$f=qx(find $basedir -iname $new) if ($new);
d26560950   Mauro Carvalho Chehab   scripts/documenta...
196
  	}
e1f319fe4   Mauro Carvalho Chehab   scripts/documenta...
197
198
199
  	# usual reason for breakage: use dash or underline
  	if (!$f) {
  		$new =~ s/[-_]/[-_]/g;
9e78e7fc0   Mauro Carvalho Chehab   scripts/documenta...
200
  		$f=qx(find $basedir -iname $new) if ($new);
e1f319fe4   Mauro Carvalho Chehab   scripts/documenta...
201
  	}
be600e5ac   Mauro Carvalho Chehab   scripts/documenta...
202
203
  	# Wild guess: seek for the same name on another place
  	if (!$f) {
9e78e7fc0   Mauro Carvalho Chehab   scripts/documenta...
204
  		$f = qx(find $basedir -iname $new) if ($new);
be600e5ac   Mauro Carvalho Chehab   scripts/documenta...
205
  	}
d26560950   Mauro Carvalho Chehab   scripts/documenta...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
  	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);
  		}
  	}
  }