blob: 1cb77710891d8c9296a90638d6153362d7f72244 [file] [log] [blame]
# Copyright 2025 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Check the content of a bundle according to a manifest."""
import sys
import os
def write_if_needed(path, content):
"""Write `content` to `path` if needed."""
if os.path.isfile(path):
# If the file exists and has the same content, skip writing.
with open(path, encoding='utf-8') as file:
if content == file.read():
return
with open(path, 'w', encoding='utf-8') as file:
file.write(content)
file.flush()
def read_manifest(manifest_path):
"""Read a manifest file."""
manifest_content = set()
with open(manifest_path, encoding='utf-8') as manifest_file:
for line in manifest_file:
assert line.endswith('\n')
manifest_content.add(line[:-1])
return manifest_content
def main(args):
if len(args) != 3:
print(
f'usage: check-manifest.py bundle-dir manifest-path output-path',
file=sys.stderr)
return 1
bundle_dir, manifest_path, output_path = args
if not os.path.isdir(bundle_dir):
print(
f'error: {bundle_dir}: not a directory',
file=sys.stderr)
return 1
has_unexpected_files = False
manifest_content = read_manifest(manifest_path)
for dirpath, dirnames, filenames in os.walk(bundle_dir):
dirnames_to_skip = []
for dirname in dirnames:
subdirpath = os.path.relpath(os.path.join(dirpath, dirname), bundle_dir)
if subdirpath in manifest_content:
dirnames_to_skip.append(dirname)
if dirnames_to_skip:
dirnames[:] = list(set(dirnames) - set(dirnames_to_skip))
for filename in filenames:
filepath = os.path.relpath(os.path.join(dirpath, filename), bundle_dir)
if filepath not in manifest_content:
fullpath = os.path.normpath(os.path.join(bundle_dir, filepath))
print(f'error: {fullpath}: unexpected file', file=sys.stderr)
has_unexpected_files = True
write_if_needed(output_path, 'ko\n' if has_unexpected_files else 'ok\n')
if has_unexpected_files:
return 1
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))