Commit 965e473a01122291e9498bbec81af144bd33f075
1 parent
f60526af
generate_auto_job: don't replace files that are unchanged
Showing
2 changed files
with
24 additions
and
11 deletions
generate_auto_job
| @@ -6,6 +6,8 @@ import hashlib | @@ -6,6 +6,8 @@ import hashlib | ||
| 6 | import re | 6 | import re |
| 7 | import yaml | 7 | import yaml |
| 8 | import json | 8 | import json |
| 9 | +import filecmp | ||
| 10 | +from contextlib import contextmanager | ||
| 9 | 11 | ||
| 10 | whoami = os.path.basename(sys.argv[0]) | 12 | whoami = os.path.basename(sys.argv[0]) |
| 11 | BANNER = f'''// | 13 | BANNER = f'''// |
| @@ -19,6 +21,17 @@ def warn(*args, **kwargs): | @@ -19,6 +21,17 @@ def warn(*args, **kwargs): | ||
| 19 | print(*args, file=sys.stderr, **kwargs) | 21 | print(*args, file=sys.stderr, **kwargs) |
| 20 | 22 | ||
| 21 | 23 | ||
| 24 | +@contextmanager | ||
| 25 | +def write_file(filename): | ||
| 26 | + tmpfile = filename + '.tmp' | ||
| 27 | + with open(tmpfile, 'w') as f: | ||
| 28 | + yield f | ||
| 29 | + if os.path.exists(filename) and filecmp.cmp(filename, tmpfile, False): | ||
| 30 | + os.unlink(tmpfile) | ||
| 31 | + else: | ||
| 32 | + os.rename(tmpfile, filename) | ||
| 33 | + | ||
| 34 | + | ||
| 22 | # QXXXQ | 35 | # QXXXQ |
| 23 | # These need manual handlers. | 36 | # These need manual handlers. |
| 24 | complex = set([ | 37 | complex = set([ |
| @@ -105,8 +118,10 @@ class Main: | @@ -105,8 +118,10 @@ class Main: | ||
| 105 | return parser.parse_args(args) | 118 | return parser.parse_args(args) |
| 106 | 119 | ||
| 107 | def top(self, options): | 120 | def top(self, options): |
| 108 | - if options.check: | ||
| 109 | - self.check() | 121 | + if self.check_hashes(): |
| 122 | + exit(0) | ||
| 123 | + elif options.check: | ||
| 124 | + exit(f'{whoami}: auto job inputs have changed') | ||
| 110 | elif options.generate: | 125 | elif options.generate: |
| 111 | self.generate() | 126 | self.generate() |
| 112 | else: | 127 | else: |
| @@ -124,7 +139,7 @@ class Main: | @@ -124,7 +139,7 @@ class Main: | ||
| 124 | pass | 139 | pass |
| 125 | return hashes | 140 | return hashes |
| 126 | 141 | ||
| 127 | - def check(self): | 142 | + def check_hashes(self): |
| 128 | hashes = self.get_hashes() | 143 | hashes = self.get_hashes() |
| 129 | match = False | 144 | match = False |
| 130 | try: | 145 | try: |
| @@ -137,8 +152,7 @@ class Main: | @@ -137,8 +152,7 @@ class Main: | ||
| 137 | match = old_hashes == hashes | 152 | match = old_hashes == hashes |
| 138 | except Exception: | 153 | except Exception: |
| 139 | pass | 154 | pass |
| 140 | - if not match: | ||
| 141 | - exit(f'{whoami}: auto job inputs have changed') | 155 | + return match |
| 142 | 156 | ||
| 143 | def update_hashes(self): | 157 | def update_hashes(self): |
| 144 | hashes = self.get_hashes() | 158 | hashes = self.get_hashes() |
| @@ -279,7 +293,6 @@ class Main: | @@ -279,7 +293,6 @@ class Main: | ||
| 279 | 293 | ||
| 280 | def generate(self): | 294 | def generate(self): |
| 281 | warn(f'{whoami}: regenerating auto job files') | 295 | warn(f'{whoami}: regenerating auto job files') |
| 282 | - | ||
| 283 | with open('job.yml', 'r') as f: | 296 | with open('job.yml', 'r') as f: |
| 284 | data = yaml.safe_load(f.read()) | 297 | data = yaml.safe_load(f.read()) |
| 285 | self.validate(data) | 298 | self.validate(data) |
| @@ -290,20 +303,20 @@ class Main: | @@ -290,20 +303,20 @@ class Main: | ||
| 290 | ) | 303 | ) |
| 291 | self.options_without_help = set(self.help_options) | 304 | self.options_without_help = set(self.help_options) |
| 292 | self.prepare(data) | 305 | self.prepare(data) |
| 293 | - with open(self.DESTS['decl'], 'w') as f: | 306 | + with write_file(self.DESTS['decl']) as f: |
| 294 | print(BANNER, file=f) | 307 | print(BANNER, file=f) |
| 295 | for i in self.decls: | 308 | for i in self.decls: |
| 296 | print(i, file=f) | 309 | print(i, file=f) |
| 297 | - with open(self.DESTS['init'], 'w') as f: | 310 | + with write_file(self.DESTS['init']) as f: |
| 298 | print(BANNER, file=f) | 311 | print(BANNER, file=f) |
| 299 | for i in self.init: | 312 | for i in self.init: |
| 300 | print(i, file=f) | 313 | print(i, file=f) |
| 301 | - with open(self.DESTS['help'], 'w') as f: | 314 | + with write_file(self.DESTS['help']) as f: |
| 302 | with open('manual/cli.rst', 'r') as df: | 315 | with open('manual/cli.rst', 'r') as df: |
| 303 | print(BANNER, file=f) | 316 | print(BANNER, file=f) |
| 304 | self.generate_doc(df, f) | 317 | self.generate_doc(df, f) |
| 305 | self.generate_schema(data) | 318 | self.generate_schema(data) |
| 306 | - with open(self.DESTS['schema'], 'w') as f: | 319 | + with write_file(self.DESTS['schema']) as f: |
| 307 | print('static constexpr char const* JOB_SCHEMA_DATA = R"(' + | 320 | print('static constexpr char const* JOB_SCHEMA_DATA = R"(' + |
| 308 | json.dumps(self.schema, indent=2, separators=(',', ': ')) + | 321 | json.dumps(self.schema, indent=2, separators=(',', ': ')) + |
| 309 | ')";', file=f) | 322 | ')";', file=f) |
job.sums
| 1 | # Generated by generate_auto_job | 1 | # Generated by generate_auto_job |
| 2 | -generate_auto_job ea845318af6d4226761f7534c489e4abe0c5f4864b2fee10c8a16f11034b4d34 | 2 | +generate_auto_job ab9b8cdb8ccf47417d265eebcf562c51bf4d5bff6abaf0920931b972f6c7b80b |
| 3 | job.yml 2752b11028530f127b06e9731834dc3ae4c3b13d0161608e3b258cd2a79767d7 | 3 | job.yml 2752b11028530f127b06e9731834dc3ae4c3b13d0161608e3b258cd2a79767d7 |
| 4 | libqpdf/qpdf/auto_job_decl.hh db95ca0864e7495532095cd193be1ff0c15797b9ccaf252024c1154bae57b365 | 4 | libqpdf/qpdf/auto_job_decl.hh db95ca0864e7495532095cd193be1ff0c15797b9ccaf252024c1154bae57b365 |
| 5 | libqpdf/qpdf/auto_job_help.hh 383eea80e2c185ef5295fc126246457a7ceeffea759fdb90bb2e6727532ea538 | 5 | libqpdf/qpdf/auto_job_help.hh 383eea80e2c185ef5295fc126246457a7ceeffea759fdb90bb2e6727532ea538 |