#!/usr/bin/env python3 """Generate distribution archives for a given FreeType 2 release.""" from __future__ import print_function import argparse import atexit import os import shutil import subprocess import sys import tempfile _TOP_DIR = os.path.abspath(os.path.join(__file__, "..", "..", "..")) _SCRIPT_DIR = os.path.dirname(os.path.join(_TOP_DIR, "builds", "meson", "")) def get_cmd_output(cmd, cwd=None): """Run a command and return its output as a string.""" if cwd is not None: out = subprocess.check_output(cmd, cwd=cwd) else: out = subprocess.check_output(cmd) return out.decode("utf-8").rstrip() def is_git_dir_clean(git_dir): """Return True iff |git_dir| is a git directory in clean state.""" out = get_cmd_output(["git", "status", "--porcelain"], cwd=git_dir) return len(out) == 0 def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "--source_dir", default=_TOP_DIR, help="Source directory path." ) parser.add_argument( "--version", help=( "Specify alternate FreeType version (it is otherwise extracted" " from current sources by default)." ), ) parser.add_argument( "--gnu-config-dir", help=( "Path of input directory containing recent `config.guess` and" " `config.sub` files from GNU config." ), ) parser.add_argument( "--build-dir", help="Specify build directory. Only used for debugging this script.", ) parser.add_argument( "--ignore-clean-check", action="store_true", help=( "Do not check for a clean source git repository. Only used for" " debugging this script." ), ) parser.add_argument( "output_dir", help="Output directory for generated archives." ) args = parser.parse_args() git_dir = args.source_dir if args.source_dir else _TOP_DIR if not args.ignore_clean_check and not is_git_dir_clean(git_dir): sys.stderr.write( "ERROR: Your git repository is not in a clean state: %s\n" % git_dir ) return 1 if args.version: version = args.version else: # Extract FreeType version from sources. version = get_cmd_output( [ sys.executable, os.path.join(_SCRIPT_DIR, "extract_freetype_version.py"), os.path.join(_TOP_DIR, "include", "freetype", "freetype.h"), ] ) # Determine the build directory. This will be a temporary file that is # cleaned up on script exit by default, unless --build-dir=DIR is used, # in which case we only create and empty the directory, but never remove # its content on exit. if args.build_dir: build_dir = args.build_dir if not os.path.exists(build_dir): os.makedirs(build_dir) else: # Remove anything from the build directory, if any. for item in os.listdir(build_dir): file_path = os.path.join(build_dir, item) if os.path.isdir(file_path): shutil.rmtree(file_path) else: os.unlink(file_path) else: # Create a temporary directory, and ensure it is removed on exit. build_dir = tempfile.mkdtemp(prefix="freetype-dist-") def clean_build_dir(): shutil.rmtree(build_dir) atexit.register(clean_build_dir) # Copy all source files known to git into $BUILD_DIR/freetype-$VERSION # with the exception of .gitignore and .mailmap files. source_files = [ f for f in get_cmd_output(["git", "ls-files"], cwd=git_dir).split("\n") if os.path.basename(f) not in (".gitignore", ".mailmap") ] freetype_dir = "freetype-" + version tmp_src_dir = os.path.join(build_dir, freetype_dir) os.makedirs(tmp_src_dir) for src in source_files: dst = os.path.join(tmp_src_dir, src) dst_dir = os.path.dirname(dst) if not os.path.exists(dst_dir): os.makedirs(dst_dir) shutil.copy(os.path.join(git_dir, src), dst) # Run autogen.sh in directory. subprocess.check_call(["/bin/sh", "autogen.sh"], cwd=tmp_src_dir) shutil.rmtree( os.path.join(tmp_src_dir, "builds", "unix", "autom4te.cache") ) # Copy config.guess and config.sub if possible! if args.gnu_config_dir: for f in ("config.guess", "config.sub"): shutil.copy( os.path.join(args.gnu_config_dir, f), os.path.join(tmp_src_dir, "builds", "unix", f), ) # Generate reference documentation under docs/ subprocess.check_call( [ sys.executable, os.path.join(_SCRIPT_DIR, "generate_reference_docs.py"), "--input-dir", tmp_src_dir, "--version", version, "--output-dir", os.path.join(tmp_src_dir, "docs"), ] ) shutil.rmtree(os.path.join(tmp_src_dir, "docs", "markdown")) os.unlink(os.path.join(tmp_src_dir, "docs", "mkdocs.yml")) # Generate our archives freetype_tar = freetype_dir + ".tar" subprocess.check_call( ["tar", "-H", "ustar", "-chf", freetype_tar, freetype_dir], cwd=build_dir, ) subprocess.check_call( ["gzip", "-9", "--keep", freetype_tar], cwd=build_dir ) subprocess.check_call(["xz", "--keep", freetype_tar], cwd=build_dir) ftwinversion = "ft" + "".join(version.split(".")) subprocess.check_call( ["zip", "-qlr9", ftwinversion + ".zip", freetype_dir], cwd=build_dir ) # Copy file to output directory now. if not os.path.exists(args.output_dir): os.makedirs(args.output_dir) for f in ( freetype_tar + ".gz", freetype_tar + ".xz", ftwinversion + ".zip", ): shutil.copy( os.path.join(build_dir, f), os.path.join(args.output_dir, f) ) # Done! return 0 if __name__ == "__main__": sys.exit(main())