From f46521234ba374cc8ba683220720f648ee4cbddf Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sat, 6 Feb 2016 23:22:16 +0000 Subject: Add python script to check licenses of a given system Change-Id: I0c6d33163a0ace003e4b34da6a058bb88306f8a7 --- scripts/licensecheck2.py | 180 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100755 scripts/licensecheck2.py diff --git a/scripts/licensecheck2.py b/scripts/licensecheck2.py new file mode 100755 index 00000000..2f009fd8 --- /dev/null +++ b/scripts/licensecheck2.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python +# Copyright (C) 2016 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import errno +import os +import re +import subprocess +import sys +import tempfile +import yaml + + +gpl3_chunks = ["autoconf", + "automake", + "bash", + "binutils", + "bison", + "ccache", + "cmake", + "flex", + "gawk", + "gcc", + "gdbm", + "gettext", + "gperf", + "groff", + "libtool", + "m4-tarball", + "make", + "nano", + "patch", + "rsync", + "texinfo-tarball"] + + +def definitions_root(): + return subprocess.check_output( + ["git", "rev-parse", "--show-toplevel"]).strip() + + +def load_yaml_file(yaml_file): + with open(yaml_file, 'r') as f: + return yaml.safe_load(f) + + +def usage(): + print ("Usage: ./licensecheck.py SYSTEM") + exit() + + +def license_file_name(repo_name, sha): + license_file = os.path.join(definitions_root(), "licenses", + repo_name + '-' + sha).strip() + return license_file + + +def check_license(repo_name, sha, clone_path): + + license_file = license_file_name(repo_name, sha) + licenses_dir = os.path.dirname(license_file) + + try: + os.makedirs(licenses_dir) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + _, license_file_temp = tempfile.mkstemp(dir=licenses_dir) + with open(license_file_temp,"wb") as out: + sys.stderr.write("Checking license of '%s' ...\n" % repo_name) + with open(os.devnull, 'w') as devnull: + subprocess.call("perl scripts/licensecheck.pl -r " + + clone_path + "|cut -d: -f2- | sort -u", + stdout=out, stderr=devnull, shell=True) + + os.rename(license_file_temp, license_file) + return license_file + + +def check_repo_if_needed(name, repo, ref): + repo_name = re.split('/|:',repo)[-1] + if repo_name.endswith(".git"): + repo_name = repo_name[:-4] + + # Check if ref is sha1 to speedup + pattern = re.compile("[0-9a-f]{40}") + if pattern.match(ref): + if os.path.isfile(license_file_name(repo_name, ref)): + return (repo, license_file_name(repo_name, ref)) + + clone_path = os.path.join(definitions_root(), "repos", repo_name) + + if os.path.isdir(clone_path): + sys.stderr.write("Updating repo '%s' ...\n" % repo_name) + with open(os.devnull, 'w') as devnull: + subprocess.call(["git", "checkout", ref], stderr=devnull, + stdout=devnull, cwd=clone_path) + else: + sys.stderr.write("Geting repo '%s' ...\n" % repo_name) + with open(os.devnull, 'w') as devnull: + subprocess.call(["morph", "get-repo", name, clone_path], + stdout=devnull, stderr=devnull) + + sha = subprocess.check_output( + ["git", "rev-parse", "HEAD"], cwd=clone_path) + + if os.path.isfile(license_file_name(repo_name, sha)): + return (repo, license_file_name(repo_name, sha)) + + return (repo, check_license(repo_name, sha, clone_path)) + + +def check_stratum(stratum_file): + stratum = load_yaml_file(stratum_file) + license_files = [] + for chunk in stratum['chunks']: + name = chunk.get("name") + build_mode = chunk.get("build-mode") + + # Don't include bootstrap chunks and stripped gplv3 chunks + if name in gpl3_chunks or build_mode == "bootstrap": + continue + repo = chunk.get("repo") + ref = chunk.get("ref") + license_to_append = check_repo_if_needed(name, repo, ref) + license_files.append(license_to_append) + return license_files + + +def main(): + if len(sys.argv) != 2: + usage() + elif (sys.argv[1] == "-h") or (sys.argv[1] == "--help"): + usage() + + system_file = sys.argv[1] + system = load_yaml_file(system_file) + license_files = [] + for stratum in system['strata']: + stratum_file = stratum['morph'] + stratum_path = os.path.join(definitions_root(), stratum_file) + license_files += check_stratum(stratum_path) + + for chunk in license_files: + try: + # Print repo name + sys.stdout.write("%s\n%s\n" % (chunk[0], '-' * len(chunk[0]))) + + # Print license file of the repo + with open(chunk[1], 'r') as f: + for line in f: + sys.stdout.write(line) + sys.stdout.write("\n") + except IOError: + # stdout is closed, no point in continuing + # Attempt to close them explicitly to prevent cleanup problems: + try: + sys.stdout.flush() + sys.stdout.close() + except IOError: + pass + finally: + exit() + + +if __name__ == "__main__": + main() -- cgit v1.2.1