1# Copyright 2023 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4"""Common logic needed by other modules.""" 5 6import contextlib 7import filecmp 8import os 9import shutil 10import tempfile 11import zipfile 12 13 14def capitalize(value): 15 return value[0].upper() + value[1:] 16 17 18def escape_class_name(fully_qualified_class): 19 """Returns an escaped string concatenating the Java package and class.""" 20 escaped = fully_qualified_class.replace('_', '_1') 21 return escaped.replace('/', '_').replace('$', '_00024') 22 23 24@contextlib.contextmanager 25def atomic_output(path, mode='w+b'): 26 with tempfile.NamedTemporaryFile(mode, delete=False) as f: 27 try: 28 yield f 29 finally: 30 f.close() 31 32 if not (os.path.exists(path) and filecmp.cmp(f.name, path)): 33 shutil.move(f.name, path) 34 if os.path.exists(f.name): 35 os.unlink(f.name) 36 37 38def add_to_zip_hermetic(zip_file, zip_path, data=None): 39 zipinfo = zipfile.ZipInfo(filename=zip_path) 40 zipinfo.external_attr = 0o644 << 16 41 zipinfo.date_time = (2001, 1, 1, 0, 0, 0) 42 zip_file.writestr(zipinfo, data, zipfile.ZIP_STORED) 43