Parse dependency versions from TF-M CMake

To make sure CI totally aligned with TF-M, it is better to automatically
parse dependency versions by CI instead of passing a fixed version via
Jenkins environment variable.

This patch adds the logic to select dependency version specified in TF-M
CMake system by default. And CI user can also manually change the
dependency version by setting the corresponding Jenkins environment
variable when triggerring CI jobs.

For the dependency version which differs from platforms, for example
tf-m-extras, the version is double checked with the value in CMake Cache
in each single build-config job.

Signed-off-by: Xinyu Zhang <xinyu.zhang@arm.com>
Change-Id: Ia528783f4235786530c7f25785facae93534c1d3
diff --git a/clone.sh b/clone.sh
index 407883d..b5b3966 100755
--- a/clone.sh
+++ b/clone.sh
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 #
-# Copyright (c) 2021-2022 Arm Limited. All rights reserved.
+# Copyright (c) 2021-2023 Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -29,59 +29,7 @@
 
 set -e
 
-# Global defaults
-GIT_CLONE_PARAMS="--no-checkout"
-
-# Must projects
-TFM_PROJECT="${CODE_REPO:?}"
-TFM_REFSPEC="${GERRIT_REFSPEC:?}"
-TFM_NAME="trusted-firmware-m"
-
-SCRIPTS_PROJECT="${CI_SCRIPTS_REPO:?}"
-SCRIPTS_REFSPEC="${CI_SCRIPTS_BRANCH:?}"
-SCRIPTS_NAME="tf-m-ci-scripts"
-
-# Optional projects
-TFM_TESTS_PROJECT="${TFM_TESTS_URL:-}"
-TFM_TESTS_REFSPEC="${TFM_TESTS_REFSPEC:-}"
-TFM_TESTS_NAME="tf-m-tests"
-
-MBEDTLS_PROJECT="${MBEDTLS_URL:-}"
-MBEDTLS_REFSPEC="${MBEDTLS_VERSION:-}"
-MBEDTLS_NAME="mbedtls"
-
-MCUBOOT_PROJECT="${MCUBOOT_URL:-}"
-MCUBOOT_REFSPEC="${MCUBOOT_REFSPEC:-}"
-MCUBOOT_NAME="mcuboot"
-
-PSA_ARCH_TESTS_PROJECT="${PSA_ARCH_TESTS_URL:-}"
-PSA_ARCH_TESTS_REFSPEC="${PSA_ARCH_TESTS_VERSION:-}"
-PSA_ARCH_TESTS_NAME="psa-arch-tests"
-
-QCBOR_PROJECT="${QCBOR_URL:-}"
-QCBOR_REFSPEC="${QCBOR_VERSION:-}"
-QCBOR_NAME="qcbor"
-
-TFM_EXTRAS_PROJECT="${TFM_EXTRAS_URL:-}"
-TFM_EXTRAS_REFSPEC="${TFM_EXTRAS_REFSPEC:-}"
-TFM_EXTRAS_NAME="tf-m-extras"
-
-QA_TOOLS_PROJECT="https://review.trustedfirmware.org/ci/qa-tools"
-QA_TOOLS_REFSPEC="openci"
-QA_TOOLS_NAME="qa-tools"
-
-# Array containing "<repo url>;"<repo name>;<refspec>" elements
-repos=(
-    "${TFM_PROJECT};${TFM_NAME};${TFM_REFSPEC}"
-    "${TFM_TESTS_PROJECT};${TFM_TESTS_NAME};${TFM_TESTS_REFSPEC}"
-    "${SCRIPTS_PROJECT};${SCRIPTS_NAME};${SCRIPTS_REFSPEC}"
-    "${MBEDTLS_PROJECT};${MBEDTLS_NAME};${MBEDTLS_REFSPEC}"
-    "${MCUBOOT_PROJECT};${MCUBOOT_NAME};${MCUBOOT_REFSPEC}"
-    "${PSA_ARCH_TESTS_PROJECT};${PSA_ARCH_TESTS_NAME};${PSA_ARCH_TESTS_REFSPEC}"
-    "${QCBOR_PROJECT};${QCBOR_NAME};${QCBOR_REFSPEC}"
-    "${TFM_EXTRAS_PROJECT};${TFM_EXTRAS_NAME};${TFM_EXTRAS_REFSPEC}"
-    "${QA_TOOLS_PROJECT};${QA_TOOLS_NAME};${QA_TOOLS_REFSPEC}"
-)
+. $(dirname $0)/util_git.sh
 
 # Take into consideration non-CI runs where SHARE_FOLDER variable
 # may not be present
@@ -96,43 +44,112 @@
 echo "Share Folder path: ${SHARE_FOLDER}"
 echo
 
-# Don't print mouthfull "You are in 'detached HEAD' state." messages.
-git config --global advice.detachedHead false
+# Parse dependency version specified in TF-M CMake configs
+function parse_version() {
+    CONFIG_FILE_NAME=$1
+    DEPENDENCY_NAME=$2
+    CONFIG_FILE_PATH="${SHARE_FOLDER}/${TFM_NAME}/${CONFIG_FILE_NAME}"
 
-# clone git repos
-for repo in ${repos[@]}; do
+    VERSION="$(grep "set(${DEPENDENCY_NAME}" ${CONFIG_FILE_PATH} | cut -d\" -f2)"
 
-    # parse the repo elements
+    if [ -z "${VERSION}" ]; then
+        VERSION="refs/heads/master"
+    fi
+
+    echo "${VERSION}"
+}
+
+# Must projects
+TFM_PROJECT="${CODE_REPO:?}"
+TFM_REFSPEC="${GERRIT_REFSPEC:?}"
+TFM_NAME="trusted-firmware-m"
+
+SCRIPTS_PROJECT="${CI_SCRIPTS_REPO:?}"
+SCRIPTS_REFSPEC="${CI_SCRIPTS_BRANCH:?}"
+SCRIPTS_NAME="tf-m-ci-scripts"
+
+# Array containing "<repo url>;"<repo name>;<refspec>" elements
+must_repos=(
+    "${TFM_PROJECT};${TFM_NAME};${TFM_REFSPEC}"
+    "${SCRIPTS_PROJECT};${SCRIPTS_NAME};${SCRIPTS_REFSPEC}"
+)
+
+for repo in ${must_repos[@]}; do
+    # Parse the repo elements
     REPO_URL="$(echo "${repo}" | awk -F ';' '{print $1}')"
     REPO_NAME="$(echo "${repo}" | awk -F ';' '{print $2}')"
     REPO_REFSPEC="$(echo "${repo}" | awk -F ';' '{print $3}')"
 
-    # in case repository is not define, just skip it
-    if [ -z "${REPO_URL}" ]; then
-        continue
-    fi
-
-    # clone and checkout in case it does not exit
-    if [ ! -d ${SHARE_FOLDER}/${REPO_NAME} ]; then
-        git clone --quiet ${GIT_CLONE_PARAMS} ${REPO_URL} ${SHARE_FOLDER}/${REPO_NAME}
-
-        # fetch and checkout the corresponding refspec
-        cd ${SHARE_FOLDER}/${REPO_NAME}
-
-        git fetch ${REPO_URL} ${REPO_REFSPEC}
-        git checkout FETCH_HEAD
-        echo -e "Share Folder ${SHARE_FOLDER}/${REPO_NAME} $(git rev-parse --short HEAD)\n"
-        cd $OLDPWD
-
+    if [ ! -d "${SHARE_FOLDER}/${REPO_NAME}" ]; then
+        git_clone $REPO_URL "${SHARE_FOLDER}/${REPO_NAME}"
+        git_checkout "${SHARE_FOLDER}/${REPO_NAME}" $REPO_REFSPEC
     else
-        # otherwise just show the head's log
-        cd ${SHARE_FOLDER}/${REPO_NAME}
-        echo -e "Share Folder ${SHARE_FOLDER}/${REPO_NAME} $(git rev-parse --short HEAD)\n"
+        cd "${SHARE_FOLDER}/${REPO_NAME}"
+        echo -e "Share Folder ${REPO_NAME} $(git rev-parse --short HEAD)\n"
         cd $OLDPWD
     fi
 
-    # copy repository into pwd dir (workspace in CI), so each job would work
+    # Copy repos into pwd dir (workspace in CI), so each job would work
     # on its own workspace
-    cp -a -f ${SHARE_FOLDER}/${REPO_NAME} ${WORKSPACE}/${REPO_NAME}
+    cp -a -f "${SHARE_FOLDER}/${REPO_NAME}" "${WORKSPACE}/${REPO_NAME}"
+done
 
+# Dependency projects
+TFM_TESTS_PROJECT="${TFM_TESTS_URL:-}"
+TFM_TESTS_REFSPEC="${TFM_TESTS_REFSPEC:-"$(parse_version lib/ext/tf-m-tests/repo_config_default.cmake TFM_TEST_REPO_VERSION)"}"
+TFM_TESTS_NAME="tf-m-tests"
+
+MBEDTLS_PROJECT="${MBEDTLS_URL:-}"
+MBEDTLS_REFSPEC="${MBEDTLS_VERSION:-"$(parse_version config/config_base.cmake MBEDCRYPTO_VERSION)"}"
+MBEDTLS_NAME="mbedtls"
+
+MCUBOOT_PROJECT="${MCUBOOT_URL:-}"
+MCUBOOT_REFSPEC="${MCUBOOT_REFSPEC:-"$(parse_version config/config_base.cmake MCUBOOT_VERSION)"}"
+MCUBOOT_NAME="mcuboot"
+
+PSA_ARCH_TESTS_PROJECT="${PSA_ARCH_TESTS_URL:-}"
+PSA_ARCH_TESTS_REFSPEC="${PSA_ARCH_TESTS_VERSION:-"$(parse_version config/config_base.cmake PSA_ARCH_TESTS_VERSION)"}"
+PSA_ARCH_TESTS_NAME="psa-arch-tests"
+
+QCBOR_PROJECT="${QCBOR_URL:-}"
+QCBOR_REFSPEC="${QCBOR_VERSION:-"$(parse_version lib/ext/qcbor/CMakeLists.txt QCBOR_VERSION)"}"
+QCBOR_NAME="qcbor"
+
+TFM_EXTRAS_PROJECT="${TFM_EXTRAS_URL:-}"
+TFM_EXTRAS_REFSPEC="${TFM_EXTRAS_REFSPEC:-"$(parse_version lib/ext/tf-m-extras/CMakeLists.txt TFM_EXTRAS_REPO_VERSION)"}"
+TFM_EXTRAS_NAME="tf-m-extras"
+
+QA_TOOLS_PROJECT="https://review.trustedfirmware.org/ci/qa-tools"
+QA_TOOLS_REFSPEC="openci"
+QA_TOOLS_NAME="qa-tools"
+
+# Array containing "<repo url>;"<repo name>;<refspec>" elements
+dependency_repos=(
+    "${TFM_TESTS_PROJECT};${TFM_TESTS_NAME};${TFM_TESTS_REFSPEC}"
+    "${MBEDTLS_PROJECT};${MBEDTLS_NAME};${MBEDTLS_REFSPEC}"
+    "${MCUBOOT_PROJECT};${MCUBOOT_NAME};${MCUBOOT_REFSPEC}"
+    "${PSA_ARCH_TESTS_PROJECT};${PSA_ARCH_TESTS_NAME};${PSA_ARCH_TESTS_REFSPEC}"
+    "${QCBOR_PROJECT};${QCBOR_NAME};${QCBOR_REFSPEC}"
+    "${TFM_EXTRAS_PROJECT};${TFM_EXTRAS_NAME};${TFM_EXTRAS_REFSPEC}"
+    "${QA_TOOLS_PROJECT};${QA_TOOLS_NAME};${QA_TOOLS_REFSPEC}"
+)
+
+for repo in ${dependency_repos[@]}; do
+    # Parse the repo elements
+    REPO_URL="$(echo "${repo}" | awk -F ';' '{print $1}')"
+    REPO_NAME="$(echo "${repo}" | awk -F ';' '{print $2}')"
+    REPO_REFSPEC="$(echo "${repo}" | awk -F ';' '{print $3}')"
+
+    if [ ! -d "${SHARE_FOLDER}/${REPO_NAME}" ]; then
+        git_clone $REPO_URL "${SHARE_FOLDER}/${REPO_NAME}"
+        git_checkout "${SHARE_FOLDER}/${REPO_NAME}" $REPO_REFSPEC
+    else
+        cd "${SHARE_FOLDER}/${REPO_NAME}"
+        echo -e "Share Folder ${REPO_NAME} $(git rev-parse --short HEAD)\n"
+        cd $OLDPWD
+    fi
+
+    # Copy repos into pwd dir (workspace in CI), so each job would work
+    # on its own workspace
+    cp -a -f "${SHARE_FOLDER}/${REPO_NAME}" "${WORKSPACE}/${REPO_NAME}"
 done