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.
diff --git a/net/README b/net/README
index a7b344f..c24990b 100644
--- a/net/README
+++ b/net/README
@@ -16,7 +16,7 @@
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 @@
# 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 @@
=== 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 @@
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 @@
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 @@
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 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}"