| # Copyright 2026 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Runs an arbitrary command and creates a stamp file upon successful completion. |
| |
| Usage: |
| run_with_stamp.py --stamp <stamp_file> [--] <command> [<command_args>...] |
| |
| Any argument starting with '@' (e.g. '@path/to/response_file.rsp') is expanded |
| in-place: |
| run_with_stamp.py @{{response_file_name}} |
| """ |
| |
| import os |
| import pathlib |
| import subprocess |
| import sys |
| |
| _SCRIPTS_BUILD_DIR = os.path.dirname(os.path.abspath(__file__)) |
| if _SCRIPTS_BUILD_DIR not in sys.path: |
| sys.path.insert(0, _SCRIPTS_BUILD_DIR) |
| |
| from response_file import expand_response_files |
| |
| |
| def main(): |
| args = expand_response_files(sys.argv[1:]) |
| |
| stamp_file = None |
| command_args = [] |
| args_iter = iter(args) |
| |
| for arg in args_iter: |
| if arg == '--stamp': |
| try: |
| stamp_file = next(args_iter) |
| except StopIteration: |
| print("Error: --stamp requires a path argument", |
| file=sys.stderr) |
| sys.exit(1) |
| elif arg.startswith('--stamp='): |
| stamp_file = arg[len('--stamp='):] |
| elif arg == '--': |
| command_args.extend(list(args_iter)) |
| break |
| else: |
| command_args.append(arg) |
| command_args.extend(list(args_iter)) |
| break |
| |
| if not stamp_file: |
| print( |
| "Usage: run_with_stamp.py --stamp <stamp_file> [--] <command> [args...]", |
| file=sys.stderr) |
| sys.exit(1) |
| |
| if not command_args: |
| print("Error: No command specified to run", file=sys.stderr) |
| sys.exit(1) |
| |
| ret = subprocess.call(command_args) |
| if ret != 0: |
| if ret < 0: |
| sys.exit(128 - ret) |
| sys.exit(ret) |
| |
| # Touch / create the stamp file only on exit code 0 |
| pathlib.Path(stamp_file).touch() |
| sys.exit(0) |
| |
| |
| if __name__ == '__main__': |
| main() |