#! python # $NetBSD: fill-placeholders.py,v 1.2 2019/11/04 18:58:30 rillig Exp $ """ Fills in some sections of data that are determined directly from the pkgsrc code, such as variable names or help topics. """ import filecmp import os import re import sys from typing import Callable, List, Match, Set from xml.sax.saxutils import escape as to_xml pkgsrcdir = os.environ['PKGSRCDIR'] def read_lines(filename: str) -> List[str]: with open(filename, 'r') as f: return f.readlines() def help_topics() -> str: # type="vert" would spread the columns over several pages, # starting with aaaa | pppp on the first page, which is # unintuitive in both the PDF and the HTML version. out = [''] for line in read_lines('help-topics.data')[2:]: topic = line.strip() out.append(f'{to_xml(topic)}') out.append('') return '\n'.join(out) def master_sites() -> str: sites = [] for line in read_lines(f'{pkgsrcdir}/mk/fetch/sites.mk'): m = re.match(r'^(MASTER_SITE_\w+)', line) if m: sites.append(m[1]) out = [''] for site in sorted(sites): out.append(f'{to_xml(site)}') out.append('') return '\n'.join(out) def process(filename: str, placeholders: Set[Callable[[], str]]): tmpl_filename = f'{filename}.tmpl' tmp_filename = f'{filename}.tmp' in_filename = tmpl_filename if os.path.isfile(tmpl_filename) else filename out_filename = filename phs = dict() for p in placeholders: phs[p.__name__] = p def repl(m: Match): return phs[m[1]]() if m[1] in phs else m[0] out = [] for line in read_lines(in_filename): out.append(re.sub(r'@(\w+)@', repl, line)) with open(tmp_filename, 'w') as f: f.writelines(out) if filecmp.cmp(tmp_filename, out_filename): os.remove(tmp_filename) elif in_filename == tmpl_filename: os.replace(tmp_filename, out_filename) else: os.rename(out_filename, tmpl_filename) os.rename(tmp_filename, out_filename) def main(): for filename in sys.argv[1:]: process(filename, {help_topics, master_sites}) if __name__ == '__main__': main()