github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/tools/check_links.py (about)

     1  #!/usr/bin/env python
     2  # Copyright 2017 syzkaller project authors. All rights reserved.
     3  # Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     4  
     5  from __future__ import print_function
     6  import os
     7  import re
     8  import sys
     9  
    10  link_re = re.compile('\[' + '[^\[\]]+' + '\]' + '\(' + '([^\(\)]+)' + '\)')
    11  
    12  if len(sys.argv) < 3:
    13  	print('Usage: <root_dir> <doc_files>...')
    14  	sys.exit(1)
    15  
    16  root = sys.argv[1]
    17  docs = sys.argv[2:]
    18  
    19  links = []
    20  
    21  for doc in docs:
    22  	with open(doc) as f:
    23  		for i, line in enumerate(f.readlines()):
    24  			for match in link_re.finditer(line):
    25  				links += [(doc, match.group(1), i + 1, match.start(1))]
    26  
    27  errors = []
    28  
    29  for link in links:
    30  	(doc, link, line, col) = link
    31  	for prefix in ['https://github.com/google/syzkaller/blob/master', 'https://github.com/google/syzkaller/tree/master']:
    32  		if link.startswith(prefix):
    33  			errors += ['%s:%d:%d: Replace absolute link with %s.' % (doc, line, col, link[len(prefix):])]
    34  
    35  def filter_link(args):
    36  	(doc, link, line, col) = args
    37  	if link.startswith('http'):
    38  		return False
    39  	if link.startswith('#'):
    40  		return False
    41  	if link.startswith('mailto'):
    42  		return False
    43  	return True
    44  
    45  links = list(filter(filter_link, links))
    46  
    47  def fix_link(args):
    48  	(doc, link, line, col) = args
    49  	link = link.split('#')[0]
    50  	link = link.split('?')[0]
    51  	return (doc, link, line, col)
    52  
    53  links = list(map(fix_link, links))
    54  
    55  def check_link(args):
    56  	(doc, link, line, col) = args
    57  	path = os.path.dirname(doc)
    58  	full_link = None
    59  	if link[0] == '/':
    60  		link = link[1:]
    61  		full_link = os.path.join(root, link)
    62  	else:
    63  		full_link = os.path.join(root, path, link)
    64  	if not os.path.exists(full_link):
    65  		return False
    66  	return True
    67  
    68  for link in links:
    69  	if not check_link(link):
    70  		(doc, link, line, col) = link
    71  		errors += ['%s:%d:%d: Broken link %s.' % (doc, line, col, link)]
    72  
    73  if len(errors) == 0:
    74  	print('%d links checked: OK' % len(links))
    75  	sys.exit(0)
    76  
    77  for error in errors:
    78  	print(error)
    79  
    80  sys.exit(2)