Initial commit.
- qa-tools public release which includes:
- trace-based coverage tool
- quality metrics measurement and tracking setup
- associated in-source documentation.
Signed-off-by: Basil Eljuse <basil.eljuse@arm.com>
diff --git a/coverage-tool/coverage-reporting/clone_sources.py b/coverage-tool/coverage-reporting/clone_sources.py
new file mode 100644
index 0000000..fb1807d
--- /dev/null
+++ b/coverage-tool/coverage-reporting/clone_sources.py
@@ -0,0 +1,151 @@
+# !/usr/bin/env python
+###############################################################################
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+###############################################################################
+
+###############################################################################
+# FILE: clone_sources.py
+#
+# DESCRIPTION: Clone the source files for code coverage
+###############################################################################
+
+import os
+import subprocess
+import json
+import time
+from random import random
+
+
+def call_cmd(cmd, print_cmd=False):
+ """
+ Function that execute an os command and returns its output
+
+ :param cmd: OS command as string
+ :param print_cmd: Optional argument to print the command in stdout
+ :return: The string output of the os command
+ """
+ if print_cmd:
+ print("+" + cmd)
+ out = subprocess.check_output(cmd, shell=True)
+ return out
+
+
+def skip_source(output_dir, source, handler=None):
+ """
+ Function that handles overwriting source files
+
+ :param output_dir: Folder where to put the source files and folders
+ :param source: Dictionary with the information the source
+ :return: True if must skip the given source cloning False otherwise
+ """
+ location = os.path.join(output_dir, source['LOCATION'])
+ # Check if exists and have files
+ if os.path.isdir(location):
+ if not os.listdir(location):
+ if handler is not None:
+ return handler(source, "Directory exists and is empty")
+ else:
+ # By default send a warning and overwrite it
+ print(("WARNING!: Directory {} already exists and is "
+ "empty. Overwriting it...'").format(location))
+ os.rmdir(location)
+ return False
+ commit_id = call_cmd(("cd {} && git log -1 2>/dev/null | "
+ "grep commit | awk '{{print $2}}'").format(
+ location), print_cmd=True).strip()
+ if source['type'] == "git":
+ if commit_id == "":
+ # is not a git
+ if handler is not None:
+ return handler(source, "Directory exists and is not git")
+ else:
+ print(("WARNING!: Directory {} already exists and is not a"
+ " git repo: '{}'").format(location, source['URL']))
+ elif commit_id != source["COMMIT"].strip():
+ # there are mismatching commit id's
+ if handler is not None:
+ return handler(source, "Mismatch in gits")
+ else:
+ print(("WARNING!: Mismatch in git repo {}\nExpected {}, "
+ "Cloned {}").format(source['URL'], source['COMMIT'],
+ commit_id))
+ elif source['type'] == "http":
+ if handler is not None:
+ return handler(source,
+ "WARNING!: Directory already exists")
+ else:
+ print("WARNING!: Directory {} already exists".format(
+ location))
+ return True
+ return False
+
+
+class CloneSources(object):
+ """Class used to clone the source code needed to produce code coverage
+ reports.
+ """
+ def __init__(self, json_file):
+ self.json_file = json_file
+ self.json_data = None
+ self.load_json()
+
+ def load_json(self):
+ with open(self.json_file, "r") as json_file:
+ self.json_data = json.load(json_file)
+
+ def clone_repo(self, output_dir, overwrite_handler=None):
+ """
+ Clones or reproduces a folder with source code based in the
+ configuration in the json file
+
+ :param output_dir: Where to put the source files
+ :param overwrite_handler: Optional function to handle overwrites
+ """
+ if self.json_data is None:
+ self.load_json()
+ sources = []
+ try:
+ if 'parameters' in self.json_data:
+ sources = self.json_data['parameters']['sources']
+ elif 'configuration' in self.json_data:
+ sources = self.json_data['configuration']['sources']
+ else:
+ raise Exception("No correct format for json sources!")
+ except Exception as ex:
+ raise Exception(ex)
+
+ for source in sources:
+ if skip_source(output_dir, source, overwrite_handler):
+ continue
+ if source['type'] == "git":
+ git = source
+ url = git["URL"]
+ commit_id = git["COMMIT"]
+ output_loc = os.path.join(output_dir, git["LOCATION"])
+ cmd = "git clone {} {}".format(url, output_loc)
+ output = call_cmd(cmd)
+ if git['REFSPEC']:
+ call_cmd("cd {};git fetch -q origin {}".format(
+ output_loc, git['REFSPEC']))
+ if commit_id:
+ call_cmd("cd {};git checkout -q {}".format(
+ output_loc, commit_id))
+ else:
+ call_cmd("cd {};git checkout -q FETCH_HEAD".format(
+ output_loc))
+ elif source['type'] == 'http':
+ site = source
+ output_loc = os.path.join(output_dir, site["LOCATION"])
+ tmp_folder = os.path.join(output_dir,
+ "_tmp_{}_{}".format(time.time(),
+ random()))
+ call_cmd("mkdir -p {}".format(tmp_folder))
+ call_cmd("wget -q {} -P {}".format(
+ site['URL'], tmp_folder))
+ call_cmd("mkdir -p {}".format(output_loc))
+ if site['COMPRESSION'] == "xz":
+ call_cmd("cd {};tar -xzf $(basename {}) -C {}".format(
+ tmp_folder, site['URL'], output_loc))
+ call_cmd("rm -rf {}".format(tmp_folder))