aboutsummaryrefslogtreecommitdiff
path: root/snapshot-update
blob: 9e9e7a1ce3df5bd506df174cfbb157d3bd4fd50c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env python3

import argparse
from hashlib import sha256
import os
import subprocess
import sys


def _main():
    args = _parse_args()
    args.func(args)


def _parse_args():
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(dest="command", required=True)

    approve_parser = subparsers.add_parser("approve")
    approve_parser.set_defaults(func=_approve)
    approve_parser.add_argument("--all", "-a", action="store_true")

    diff_parser = subparsers.add_parser("diff")
    diff_parser.set_defaults(func=_diff)
    diff_parser.add_argument("code", nargs="?")

    ls_parser = subparsers.add_parser("ls")
    ls_parser.set_defaults(func=_ls)

    reject_parser = subparsers.add_parser("reject")
    reject_parser.set_defaults(func=_reject)
    reject_parser.add_argument("--all", "-a", action="store_true")

    return parser.parse_args()


def _approve(args):
    if args.all:
        for path in _find_actual_paths():
            expected_path = _actual_path_to_expected_path(path)
            print("replace\n    {}\nwith\n    {}".format(expected_path, path), file=sys.stderr)
            os.replace(path, expected_path)
    else:
        raise Exception("not implemented yet")


def _diff(args):
    if args.code is None:
        for actual_path in _find_actual_paths():
            _render_diff(actual_path)
            print()

    else:
        matches = []

        for actual_path in _find_actual_paths():
            name = _path_to_name(actual_path)
            code = _name_to_code(name)
            if code.startswith(args.code):
                matches.append(actual_path)

        if len(matches) == 0:
            raise ValueError(f"could not find {args.code}")
        elif len(matches) > 1:
            raise ValueError(f"multiple matches for {args.code}")
        else:
            actual_path = matches[0]
            _render_diff(actual_path)


def _render_diff(actual_path):
    expected_path = _actual_path_to_expected_path(actual_path)
    name = _path_to_name(actual_path)
    code = _name_to_code(name)
    print("Code:", code)
    print("Name:", name, flush=True)
    subprocess.run(["colordiff", "-u", "--new-file", expected_path, actual_path])


def _ls(args):
    for actual_path in _find_actual_paths():
        name = _path_to_name(actual_path)
        code = _name_to_code(name)
        print("Code:", code)
        print("Name:", name)
        print()


def _reject(args):
    if args.all:
        for path in _find_actual_paths():
            print("delete\n    {}".format(path), file=sys.stderr)
            os.unlink(path)
    else:
        raise Exception("not implemented yet")


def _find_actual_paths():
    for root, dirnames, filenames in os.walk(_snapshots_path()):
        for filename in filenames:
            path = os.path.join(root, filename)
            if _has_extension(path, "actual"):
                yield path


def _snapshots_path():
    return os.path.join(os.path.dirname(__file__), "snapshots")


def _has_extension(path, extension):
    return os.path.splitext(path)[1] == "." + extension


def _actual_path_to_expected_path(actual_path):
    return _replace_extension(actual_path, "expected")


def _replace_extension(path, extension):
    return _remove_extension(path) + "." + extension


def _remove_extension(path):
    return os.path.splitext(path)[0]


def _path_to_name(path):
    return os.path.relpath(os.path.splitext(path)[0], _snapshots_path())


def _name_to_code(name):
    return sha256(name.encode("utf8")).hexdigest()


if __name__ == "__main__":
    _main()