blob: 7eb23048cbc5a7131397293223651429b172ba1a [file] [log] [blame]
lowRISC Contributors802543a2019-08-31 12:12:56 +01001#!/usr/bin/env python3
2# Copyright lowRISC contributors.
3# Licensed under the Apache License, Version 2.0, see LICENSE for details.
4# SPDX-License-Identifier: Apache-2.0
5"""Show a diff between the generated output from utils in the current working
6tree versus a previous revision (HEAD by default). This makes it easy to
7inspect the impact of modifications to either the utility implementation or
8its input files on the generated output (e.g. HTML).
9"""
10
11import argparse
12import os
13import shlex
14import subprocess
15import sys
16import tempfile
17
18from reggen import version
19
20# Test list format:
21# output, outisdir, commandpre, commandpost
22# if outisdir then it will be mkdired
23# command is commandpre + fullpath_output + commandpost
24
25testlist = [
lowRISC Contributors802543a2019-08-31 12:12:56 +010026 ["regdoc.md", False,
27 "./regtool.py --doc > ", ""],
lowRISC Contributors802543a2019-08-31 12:12:56 +010028 ["uart_rtl", True,
Tobias Wölfel4c5fbec2019-10-23 12:43:17 +020029 "./regtool.py -r -t ", " ../hw/ip/uart/data/uart.hjson"],
lowRISC Contributors802543a2019-08-31 12:12:56 +010030 ["uart_dv", True,
Tobias Wölfel4c5fbec2019-10-23 12:43:17 +020031 "./regtool.py -s -t ", " ../hw/ip/uart/data/uart.hjson"],
lowRISC Contributors802543a2019-08-31 12:12:56 +010032 # generating include define headers
33 ["uart.h", False,
Tobias Wölfel4c5fbec2019-10-23 12:43:17 +020034 "./regtool.py -D ../hw/ip/uart/data/uart.hjson > ", ""],
lowRISC Contributors802543a2019-08-31 12:12:56 +010035 ["gpio.h", False,
Tobias Wölfel4c5fbec2019-10-23 12:43:17 +020036 "./regtool.py -D ../hw/ip/gpio/data/gpio.hjson > ", ""],
lowRISC Contributors802543a2019-08-31 12:12:56 +010037 ["spi_device.h", False,
Tobias Wölfel4c5fbec2019-10-23 12:43:17 +020038 "./regtool.py -D ../hw/ip/spi_device/data/spi_device.hjson > ", ""]
Tobias Wölfelb4b624d2020-05-15 11:06:07 +020039] # yapf: disable
lowRISC Contributors802543a2019-08-31 12:12:56 +010040
41
42def generate_output(outdir, verbose):
43 for t in testlist:
44 out = shlex.quote(os.path.join(outdir, t[0]))
45 if t[1]:
46 # in new tmpdir so the directory should never be there already
47 os.mkdir(out)
48 errors_out = open(out + ".STDERR", 'w', encoding='UTF-8')
49 with errors_out:
50 err = subprocess.call(t[2] + out + t[3],
51 stderr=errors_out,
52 shell=True)
53 # write a file so it pops up in the diff
54 # if it is different
55 # (i.e. won't mention any that always return same error)
56 if err != 0:
57 rtn_out = open(out + ".RETURN", 'w', encoding='UTF-8')
58 with rtn_out:
59 rtn_out.write("Non-Zero Return code " + str(err) + "\n")
60
61 # useful for debug:
62 if (verbose):
63 subprocess.call("ls -l " + outdir, shell=True)
64
65
66def main():
67 parser = argparse.ArgumentParser(
68 description=__doc__,
69 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
70 parser.add_argument("treeish",
71 default="HEAD",
72 nargs="?",
73 help="git tree or commit to compare against")
74 parser.add_argument('--version',
75 action='store_true',
76 help='Show version and exit')
77 parser.add_argument('-v',
78 '--verbose',
79 action='store_true',
80 help='Verbose output: ls the output directories')
81
82 args = parser.parse_args()
83 if args.version:
84 version.show_and_exit(__file__, [])
85 args.treeish = shlex.quote(args.treeish)
86
87 util_path = os.path.dirname(os.path.realpath(__file__))
88 repo_root = os.path.abspath(os.path.join(util_path, os.pardir))
89 os.chdir(repo_root)
90
91 if not os.path.isdir(os.path.join(repo_root, '.git')):
92 print("Script not in expected location in a git repo", file=sys.stderr)
93 sys.exit(1)
94
95 # Exit early if there are no diffs between the working tree and
96 # args.treeish.
97 output = subprocess.check_output("git diff " + args.treeish, shell=True)
98 if not output:
99 sys.exit(0)
100
101 # Create temporary directories in util_path rather than defaulting to /tmp.
102 # /tmp may be small and may may be mounted noexec.
103 tempfile.tempdir = util_path
104
105 with tempfile.TemporaryDirectory() as tmpdir:
106 tmpdir_basename = os.path.basename(tmpdir)
107 subprocess.check_call("git archive " + args.treeish +
108 " | tar -x -C util/" + tmpdir_basename,
109 shell=True)
110
111 # Execute commands for working tree, saving output
112 os.chdir(util_path)
113 newoutdir = os.path.join(tmpdir, "newout")
114 os.mkdir(newoutdir)
115 generate_output(newoutdir, args.verbose)
116
117 # Execute commands for previous revision, saving output
118 os.chdir(os.path.join(tmpdir_basename, "util"))
119 oldoutdir = os.path.join(tmpdir, "oldout")
120 os.mkdir(oldoutdir)
121 generate_output(oldoutdir, args.verbose)
122
123 # Show diff (if any)
124 os.chdir(tmpdir)
125 # Don't use a checked call because the exit code indicates whether there
126 # is a diff or not, rather than indicating error.
127 subprocess.call('git diff -p --stat --no-index oldout newout',
128 shell=True)
129
130
131if __name__ == "__main__":
132 main()