Neels Hofmeyr | 697a617 | 2018-08-22 17:32:21 +0200 | [diff] [blame^] | 1 | #!/usr/bin/env python3 |
| 2 | |
| 3 | import os, sys, re, shutil |
| 4 | |
| 5 | def get_arg(nr, default): |
| 6 | if len(sys.argv) > nr: |
| 7 | return sys.argv[nr] |
| 8 | return default |
| 9 | |
| 10 | local_config_file = os.path.realpath(get_arg(1, 'local_config')) |
| 11 | tmpl_dir = get_arg(2, 'tmpl') |
| 12 | |
| 13 | if not os.path.isdir(tmpl_dir): |
| 14 | print("Template dir does not exist: %r" % tmpl_dir) |
| 15 | exit(1) |
| 16 | |
| 17 | print('using config file %r\non templates %r' % (local_config_file, tmpl_dir)) |
| 18 | |
| 19 | # read in variable values from config file |
| 20 | local_config = {} |
| 21 | |
| 22 | line_nr = 0 |
| 23 | for line in open(local_config_file): |
| 24 | line_nr += 1 |
| 25 | line = line.strip('\n') |
| 26 | if not '=' in line: |
| 27 | if line: |
| 28 | print("Error: %r line %d: %r" % (local_config_file, line_nr, line)) |
| 29 | exit(1) |
| 30 | continue |
| 31 | |
| 32 | split_pos = line.find('=') |
| 33 | name = line[:split_pos] |
| 34 | val = line[split_pos + 1:] |
| 35 | |
| 36 | if val.startswith('"') and val.endswith('"'): |
| 37 | val = val[1:-1] |
| 38 | |
| 39 | if name in local_config: |
| 40 | print("Error: duplicate identifier in %r line %d: %r" % (local_config_file, line_nr, line)) |
| 41 | local_config[name] = val |
| 42 | |
| 43 | print('config:\n\n' + '\n'.join('%s=%r' % (n,v) for n,v in local_config.items())) |
| 44 | |
| 45 | # replace variable names with above values recursively |
| 46 | replace_re = re.compile('\$\{([A-Za-z0-9_]*)\}') |
| 47 | command_re = re.compile('\$\{([A-Za-z0-9_]*)\(([^)]*)\)\}') |
| 48 | |
| 49 | idx = 0 |
| 50 | |
| 51 | for tmpl_name in sorted(os.listdir(tmpl_dir)): |
| 52 | tmpl_src = os.path.join(tmpl_dir, tmpl_name) |
| 53 | dst = tmpl_name |
| 54 | |
| 55 | local_config['_fname'] = tmpl_name |
| 56 | local_config['_name'] = os.path.splitext(tmpl_name)[0] |
| 57 | local_config['_idx0'] = str(idx) |
| 58 | idx += 1 |
| 59 | local_config['_idx1'] = str(idx) |
| 60 | |
| 61 | try: |
| 62 | result = open(tmpl_src).read() |
| 63 | except: |
| 64 | print('Error in %r' % tmpl_src) |
| 65 | raise |
| 66 | |
| 67 | while True: |
| 68 | used_vars = set() |
| 69 | for m in command_re.finditer(result): |
| 70 | cmd = m.group(1) |
| 71 | arg = m.group(2) |
| 72 | if cmd == 'include': |
| 73 | include_path = os.path.join(tmpl_dir, arg) |
| 74 | if not os.path.isfile(include_path): |
| 75 | print('Error: included file does not exist: %r in %r' % (include_path, tmpl_src)) |
| 76 | exit(1) |
| 77 | try: |
| 78 | incl = open(include_path).read() |
| 79 | except: |
| 80 | print('Cannot read %r for %r' % (include_path, tmpl_src)) |
| 81 | raise |
| 82 | result = result.replace('${%s(%s)}' % (cmd, arg), incl) |
| 83 | else: |
| 84 | print('Error: unknown command: %r in %r' % (cmd, tmpl_src)) |
| 85 | exit(1) |
| 86 | |
| 87 | for m in replace_re.finditer(result): |
| 88 | name = m.group(1) |
| 89 | if not name in local_config: |
| 90 | print('Error: undefined var %r in %r' % (name, tmpl_src)) |
| 91 | exit(1) |
| 92 | used_vars.add(name) |
| 93 | |
| 94 | if not used_vars: |
| 95 | break |
| 96 | |
| 97 | for var in used_vars: |
| 98 | result = result.replace('${%s}' % var, local_config.get(var)) |
| 99 | |
| 100 | with open(dst, 'w') as dst_file: |
| 101 | dst_file.write(result) |
| 102 | |
| 103 | shutil.copymode(tmpl_src, dst) |
| 104 | |
| 105 | # vim: ts=2 sw=2 expandtab |