blob: 99c80abc86cc278f0ae2d9ab8ceb60b3656cb7b5 [file] [log] [blame]
Basil Eljuse4b14afb2020-09-30 13:07:23 +01001# !/usr/bin/env python
2###############################################################################
3# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
4#
5# SPDX-License-Identifier: BSD-3-Clause
6###############################################################################
7
8###############################################################################
9# FILE: clone_sources.py
10#
11# DESCRIPTION: Clone the source files for code coverage
12###############################################################################
13
14import os
15import subprocess
16import json
17import time
18from random import random
19
20
Saul Romero884d2142023-01-16 10:31:22 +000021def call_cmd(cmd, print_cmd=True):
Basil Eljuse4b14afb2020-09-30 13:07:23 +010022 """
23 Function that execute an os command and returns its output
24
25 :param cmd: OS command as string
26 :param print_cmd: Optional argument to print the command in stdout
27 :return: The string output of the os command
28 """
29 if print_cmd:
30 print("+" + cmd)
31 out = subprocess.check_output(cmd, shell=True)
32 return out
33
34
35def skip_source(output_dir, source, handler=None):
36 """
37 Function that handles overwriting source files
38
39 :param output_dir: Folder where to put the source files and folders
40 :param source: Dictionary with the information the source
41 :return: True if must skip the given source cloning False otherwise
42 """
43 location = os.path.join(output_dir, source['LOCATION'])
44 # Check if exists and have files
45 if os.path.isdir(location):
46 if not os.listdir(location):
47 if handler is not None:
48 return handler(source, "Directory exists and is empty")
49 else:
50 # By default send a warning and overwrite it
51 print(("WARNING!: Directory {} already exists and is "
52 "empty. Overwriting it...'").format(location))
53 os.rmdir(location)
54 return False
55 commit_id = call_cmd(("cd {} && git log -1 2>/dev/null | "
56 "grep commit | awk '{{print $2}}'").format(
57 location), print_cmd=True).strip()
58 if source['type'] == "git":
59 if commit_id == "":
60 # is not a git
61 if handler is not None:
62 return handler(source, "Directory exists and is not git")
63 else:
64 print(("WARNING!: Directory {} already exists and is not a"
65 " git repo: '{}'").format(location, source['URL']))
66 elif commit_id != source["COMMIT"].strip():
67 # there are mismatching commit id's
68 if handler is not None:
69 return handler(source, "Mismatch in gits")
70 else:
71 print(("WARNING!: Mismatch in git repo {}\nExpected {}, "
72 "Cloned {}").format(source['URL'], source['COMMIT'],
73 commit_id))
Saul Romero7438b3d2024-08-20 16:12:40 +010074 return True
Basil Eljuse4b14afb2020-09-30 13:07:23 +010075 elif source['type'] == "http":
76 if handler is not None:
77 return handler(source,
78 "WARNING!: Directory already exists")
79 else:
80 print("WARNING!: Directory {} already exists".format(
81 location))
82 return True
83 return False
84
85
86class CloneSources(object):
87 """Class used to clone the source code needed to produce code coverage
88 reports.
89 """
90 def __init__(self, json_file):
91 self.json_file = json_file
92 self.json_data = None
93 self.load_json()
94
95 def load_json(self):
96 with open(self.json_file, "r") as json_file:
97 self.json_data = json.load(json_file)
98
99 def clone_repo(self, output_dir, overwrite_handler=None):
100 """
101 Clones or reproduces a folder with source code based in the
102 configuration in the json file
103
104 :param output_dir: Where to put the source files
105 :param overwrite_handler: Optional function to handle overwrites
106 """
107 if self.json_data is None:
108 self.load_json()
109 sources = []
110 try:
111 if 'parameters' in self.json_data:
112 sources = self.json_data['parameters']['sources']
113 elif 'configuration' in self.json_data:
114 sources = self.json_data['configuration']['sources']
115 else:
116 raise Exception("No correct format for json sources!")
117 except Exception as ex:
118 raise Exception(ex)
119
120 for source in sources:
121 if skip_source(output_dir, source, overwrite_handler):
122 continue
123 if source['type'] == "git":
124 git = source
125 url = git["URL"]
126 commit_id = git["COMMIT"]
127 output_loc = os.path.join(output_dir, git["LOCATION"])
Saul Romero7438b3d2024-08-20 16:12:40 +0100128 cmd = "rm -rf {1} || true;git clone {0} {1}".format(url, output_loc)
Basil Eljuse4b14afb2020-09-30 13:07:23 +0100129 output = call_cmd(cmd)
130 if git['REFSPEC']:
131 call_cmd("cd {};git fetch -q origin {}".format(
132 output_loc, git['REFSPEC']))
133 if commit_id:
134 call_cmd("cd {};git checkout -q {}".format(
135 output_loc, commit_id))
136 else:
137 call_cmd("cd {};git checkout -q FETCH_HEAD".format(
138 output_loc))
Saul Romero884d2142023-01-16 10:31:22 +0000139 call_cmd("cd {};git submodule update --init --recursive || true".format(output_loc))
Basil Eljuse4b14afb2020-09-30 13:07:23 +0100140 elif source['type'] == 'http':
141 site = source
142 output_loc = os.path.join(output_dir, site["LOCATION"])
143 tmp_folder = os.path.join(output_dir,
144 "_tmp_{}_{}".format(time.time(),
145 random()))
146 call_cmd("mkdir -p {}".format(tmp_folder))
147 call_cmd("wget -q {} -P {}".format(
148 site['URL'], tmp_folder))
149 call_cmd("mkdir -p {}".format(output_loc))
150 if site['COMPRESSION'] == "xz":
Saul Romero884d2142023-01-16 10:31:22 +0000151 call_cmd("cd {};tar -xzf $(basename {}) -C {} {}".format(
152 tmp_folder, site['URL'], output_loc,
153 source.get("EXTRA_PARAMS", "")))
Basil Eljuse4b14afb2020-09-30 13:07:23 +0100154 call_cmd("rm -rf {}".format(tmp_folder))