From 57e4288c8608c5c86d2ef880e8fe6a31f37aecb3 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 23 Aug 2018 15:19:35 +0200 Subject: [PATCH] include cfg.sh,stale_config.sh in fill_config.py Staleness check now also checks for included files. fill_config.py figures out last used paths itself and has cmdline doc. --- net/README | 12 +++---- net/cfg.sh | 44 ----------------------- net/fill_config.py | 86 ++++++++++++++++++++++++++++++++++++++------- net/stale_config.sh | 17 --------- net/tmpl_std/run.sh | 2 +- 5 files changed, 80 insertions(+), 81 deletions(-) delete mode 100755 net/cfg.sh delete mode 100755 net/stale_config.sh diff --git a/net/README b/net/README index a7b344f..c24990b 100644 --- a/net/README +++ b/net/README @@ -16,7 +16,7 @@ $EDITOR config_mine mkdir my_network cd my_network -../cfg.sh ../config_mine ../tmpl_std +../fill_config.py ../config_mine ../tmpl_std ./run.sh # Launches numerous x-terminals with one component running in each. @@ -30,13 +30,13 @@ Then possibly modify the config and refresh: # tweak config? $EDITOR ../config_mine -../cfg.sh +../fill_config.py # picks up same ../config_mine and ../tmpl_std from last time # own templates? cp -r ../tmpl_std ../tmpl_mine $EDITOR ../tmpl_mine/* -../cfg.sh ../tmpl_mine +../fill_config.py ../tmpl_mine # picks up same ../config_mine from last time, and ../tmpl_mine from cmdline @@ -44,13 +44,13 @@ $EDITOR ../tmpl_mine/* === Config file templates A *directory* contains template files that are filled with specific values by the -cfg.sh script (aided by fill_config.py). See e.g. tmpl_std/. +fill_config.py script. See e.g. tmpl_std/. A *file* contains local config items that are put into the templates. See e.g. config_2g3g. -The cfg.sh script helps to fill the templates with the config values. Simply -invoke cfg.sh with a dir argument (templates dir) and a file argument (specific +The fill_config.py script helps to fill the templates with the config values. Simply +invoke fill_config.py with a dir argument (templates dir) and a file argument (specific config values). If one or both are omitted, the script tries to re-use the most recent paths, diff --git a/net/cfg.sh b/net/cfg.sh deleted file mode 100755 index 4dda0af..0000000 --- a/net/cfg.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh -config_file="" -tmpl_dir="" - -while test -n "$1"; do - arg="$1" - shift - - if [ ! -e "$arg" ]; then - if [ -e "../$arg"]; then - arg="../$arg"; - fi - fi - - if [ -f "$arg" ]; then - if [ -n "$config_file" ]; then - echo "Error: more than one config file: '$config_file' and '$arg'" - exit 2 - fi - config_file="$arg" - fi - - if [ -d "$arg" ]; then - if [ -n "$tmpl_dir" ]; then - echo "Error: more than one template dir: '$tmpl_dir' and '$arg'" - exit 2 - fi - tmpl_dir="$arg" - fi -done - -if [ -z "$config_file" ]; then - config_file="$(cat .last_config)" -fi - -if [ -z "$tmpl_dir" ]; then - tmpl_dir="$(cat .last_templates)" -fi - -set -e -../fill_config.py "$config_file" "$tmpl_dir" - -echo "$config_file" > .last_config -echo "$tmpl_dir" > .last_templates diff --git a/net/fill_config.py b/net/fill_config.py index 24ce303..09b515f 100755 --- a/net/fill_config.py +++ b/net/fill_config.py @@ -1,21 +1,63 @@ #!/usr/bin/env python3 +'''Take values from a config file and fill them into a set of templates. +Write the result to the current directory.''' import os, sys, re, shutil +import argparse -def get_arg(nr, default): - if len(sys.argv) > nr: - return sys.argv[nr] - return default +def file_newer(path_a, than_path_b): + return os.path.getmtime(path_a) > os.path.getmtime(than_path_b) -local_config_file = os.path.realpath(get_arg(1, 'local_config')) -tmpl_dir = get_arg(2, 'tmpl') +LAST_LOCAL_CONFIG_FILE = '.last_config' +LAST_TMPL_DIR = '.last_templates' -if not os.path.isdir(tmpl_dir): +parser = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) +parser.add_argument('sources', metavar='SRC', nargs='*', + help='Pass both a template directory and a config file.') +parser.add_argument('-s', '--check-stale', dest='check_stale', action='store_true', + help='only verify age of generated files vs. config and templates.' + ' Exit nonzero when any source file is newer. Do not write anything.') + +args = parser.parse_args() + +local_config_file = None +tmpl_dir = None + +for src in args.sources: + if os.path.isdir(src): + if tmpl_dir is not None: + print('Error: only one template dir permitted. (%r vs. %r)' % (tmpl_dir, src)) + tmpl_dir = src + elif os.path.isfile(src): + if local_config_file is not None: + print('Error: only one config file permitted. (%r vs. %r)' % (local_config_file, src)) + local_config_file = src + +if local_config_file is None and os.path.isfile(LAST_LOCAL_CONFIG_FILE): + local_config_file = open(LAST_LOCAL_CONFIG_FILE).read().strip() + +if tmpl_dir is None and os.path.isfile(LAST_TMPL_DIR): + tmpl_dir = open(LAST_TMPL_DIR).read().strip() + +if not tmpl_dir or not os.path.isdir(tmpl_dir): print("Template dir does not exist: %r" % tmpl_dir) exit(1) +if not local_config_file or not os.path.isfile(local_config_file): + print("No such config file: %r" % tmpl_dir) + exit(1) + +local_config_file = os.path.realpath(local_config_file) +tmpl_dir = os.path.realpath(tmpl_dir) + print('using config file %r\non templates %r' % (local_config_file, tmpl_dir)) +with open(LAST_LOCAL_CONFIG_FILE, 'w') as last_file: + last_file.write(local_config_file) +with open(LAST_TMPL_DIR, 'w') as last_file: + last_file.write(tmpl_dir) + # read in variable values from config file local_config = {} @@ -23,6 +65,10 @@ line_nr = 0 for line in open(local_config_file): line_nr += 1 line = line.strip('\n') + + if line.startswith('#'): + continue + if not '=' in line: if line: print("Error: %r line %d: %r" % (local_config_file, line_nr, line)) @@ -40,18 +86,30 @@ for line in open(local_config_file): print("Error: duplicate identifier in %r line %d: %r" % (local_config_file, line_nr, line)) local_config[name] = val -print('config:\n\n' + '\n'.join('%s=%r' % (n,v) for n,v in local_config.items())) - # replace variable names with above values recursively replace_re = re.compile('\$\{([A-Za-z0-9_]*)\}') command_re = re.compile('\$\{([A-Za-z0-9_]*)\(([^)]*)\)\}') idx = 0 +def check_stale(src_path, target_path): + if file_newer(src_path, target_path): + print('Stale: %r is newer than %r' % (src_path, target_path)) + exit(1) + for tmpl_name in sorted(os.listdir(tmpl_dir)): + + # omit "hidden" files + if tmpl_name.startswith('.'): + continue + tmpl_src = os.path.join(tmpl_dir, tmpl_name) dst = tmpl_name + if args.check_stale: + check_stale(local_config_file, dst) + check_stale(tmpl_src, dst) + local_config['_fname'] = tmpl_name local_config['_name'] = os.path.splitext(tmpl_name)[0] local_config['_idx0'] = str(idx) @@ -79,6 +137,8 @@ for tmpl_name in sorted(os.listdir(tmpl_dir)): except: print('Cannot read %r for %r' % (include_path, tmpl_src)) raise + if args.check_stale: + check_stale(include_path, dst) result = result.replace('${%s(%s)}' % (cmd, arg), incl) else: print('Error: unknown command: %r in %r' % (cmd, tmpl_src)) @@ -97,9 +157,9 @@ for tmpl_name in sorted(os.listdir(tmpl_dir)): for var in used_vars: result = result.replace('${%s}' % var, local_config.get(var)) - with open(dst, 'w') as dst_file: - dst_file.write(result) - - shutil.copymode(tmpl_src, dst) + if not args.check_stale: + with open(dst, 'w') as dst_file: + dst_file.write(result) + shutil.copymode(tmpl_src, dst) # vim: ts=2 sw=2 expandtab diff --git a/net/stale_config.sh b/net/stale_config.sh deleted file mode 100755 index f849ce1..0000000 --- a/net/stale_config.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -stale="0" -for f in *.cfg; do - f="$(basename "$f")" - for g in $(find . -maxdepth 2 -name "$f" -or -name "common_logging") ; do - if [ "$f" -ot "$g" ]; then - stale="1" - echo "$f older than $g" - fi - done -done - -if [ "$stale" = "1" ]; then - echo "Stale configs. Hit enter to continue anyway." - read ok_to_continue -fi diff --git a/net/tmpl_std/run.sh b/net/tmpl_std/run.sh index d9ec53d..8d71804 100755 --- a/net/tmpl_std/run.sh +++ b/net/tmpl_std/run.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -../stale_config.sh +../fill_config.py --check-stale || ( echo "STALE CONFIGS. Hit enter to continue anyway."; read enter_to_continue ) dev="${ETH_DEV}" ip2="${PUBLIC_IP2}"