| #!/usr/bin/python3 |
| # Copyright 2019 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """ |
| Generate the output directory for the fonts LUCI recipe. |
| """ |
| |
| import argparse |
| import errno |
| import glob |
| import json |
| import os |
| import re |
| from distutils import dir_util |
| |
| FONT_EXTENSIONS = frozenset([".ttf", ".ttc", ".otf"]) |
| """Supported font file extensions.""" |
| |
| SAFE_NAME_PATTERN = re.compile(r'[^a-z0-9\-]') |
| """Characters allowed in "safe name", part of GN package name.""" |
| |
| |
| def copy_all_staging_files(staging_dir, output_dir): |
| dir_util.copy_tree(staging_dir, output_dir, update=True) |
| |
| |
| def to_safe_name(file_name): |
| safe_name = file_name.lower() |
| safe_name = SAFE_NAME_PATTERN.sub('-', safe_name) |
| return safe_name |
| |
| |
| def get_path_prefix(root_dir, current_dir): |
| """Generate the `path_prefix` field for a font_pkgs entry.""" |
| rel_path = os.path.relpath(current_dir, start=root_dir) |
| return '' if rel_path == '.' else (rel_path + '/') |
| |
| |
| def get_catalog_name(staging_dir): |
| """Find font catalog file in output directory and get its base name.""" |
| pattern = os.path.join(staging_dir, '*.font_catalog.json') |
| catalogs = glob.glob(pattern) |
| if not catalogs: |
| raise IOError(errno.ENOENT, |
| 'Could not find font catalog file') |
| catalog_name = os.path.basename(catalogs[0]) |
| return catalog_name[0:catalog_name.find('.font_catalog.json')] |
| |
| |
| def makedirs(path, exist_ok=False): |
| try: |
| os.makedirs(path) |
| except OSError as e: |
| if not exist_ok or e.errno != errno.EEXIST: |
| raise |
| |
| |
| def generate_font_pkgs_json(output_dir, catalog_name): |
| """Generate .font_pkgs.json file in the output directory.""" |
| entries = [] |
| for current_dir, dirs, files in os.walk(output_dir): |
| for file_name in files: |
| extension = os.path.splitext(file_name)[1].lower() |
| if extension not in FONT_EXTENSIONS: |
| continue |
| entry = { |
| 'file_name': file_name, |
| 'safe_name': to_safe_name(file_name), |
| 'path_prefix': get_path_prefix(output_dir, current_dir), |
| } |
| entries.append(entry) |
| entries.sort(key=lambda entry: entry['safe_name']) |
| output = { |
| 'version': '1', |
| 'packages': entries |
| } |
| output_file_name = catalog_name + '.font_pkgs.json' |
| output_file_path = os.path.join(output_dir, output_file_name) |
| with open(output_file_path, 'w') as file: |
| json.dump(output, file, indent=2) |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser( |
| description="Pack font and JSON files for LUCI recipe") |
| parser.add_argument('output_dir', metavar='output-dir', type=str) |
| parser.add_argument('--staging-dir', type=str, default='.', |
| help='Defaults to current working directory') |
| args = parser.parse_args() |
| |
| output_dir = os.path.abspath(args.output_dir) |
| staging_dir = os.path.abspath(args.staging_dir) |
| |
| script_path = os.path.abspath(__file__) |
| assert os.path.dirname( |
| script_path) != staging_dir, 'Script %s should not be in staging directory' % script_path |
| |
| makedirs(output_dir, exist_ok=True) |
| |
| catalog_name = get_catalog_name(staging_dir) |
| copy_all_staging_files(staging_dir, output_dir) |
| generate_font_pkgs_json(output_dir, catalog_name) |
| |
| |
| if __name__ == '__main__': |
| main() |